summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
authorYong He <yonghe@outlook.com>2020-06-25 16:29:07 -0700
committerYong He <yonghe@outlook.com>2020-06-25 16:29:07 -0700
commit218a39b65c86654772c3d6adf2479e7cadc85d24 (patch)
treec636a65ff1ed8c347f10f4e9c2c6a703fd9ad8ad /source
parent509e36b62de7578843abc2547921beadff7a3ce0 (diff)
remove ThisPointerDecoration, generate IRInterfaceType in one pass
Diffstat (limited to 'source')
-rw-r--r--source/slang/slang-emit-cpp.cpp50
-rw-r--r--source/slang/slang-ir-inst-defs.h9
-rw-r--r--source/slang/slang-ir-insts.h13
-rw-r--r--source/slang/slang-ir-lower-generics.cpp1
-rw-r--r--source/slang/slang-ir.cpp5
-rw-r--r--source/slang/slang-ir.h5
-rw-r--r--source/slang/slang-lower-to-ir.cpp85
7 files changed, 90 insertions, 78 deletions
diff --git a/source/slang/slang-emit-cpp.cpp b/source/slang/slang-emit-cpp.cpp
index f895b1119..7f743d9e0 100644
--- a/source/slang/slang-emit-cpp.cpp
+++ b/source/slang/slang-emit-cpp.cpp
@@ -1617,12 +1617,27 @@ void CPPSourceEmitter::_emitWitnessTableWrappers()
{
for (auto witnessTable : pendingWitnessTableDefinitions)
{
+ auto interfaceType = cast<IRInterfaceType>(witnessTable->getOperand(0));
for (auto child : witnessTable->getChildren())
{
if (auto entry = as<IRWitnessTableEntry>(child))
{
if (auto funcVal = as<IRFunc>(entry->getSatisfyingVal()))
{
+ IRInst* requirementVal = nullptr;
+ for (UInt i = 0; i < interfaceType->getOperandCount(); i++)
+ {
+ if (auto reqEntry = as<IRInterfaceRequirementEntry>(interfaceType->getOperand(i)))
+ {
+ if (reqEntry->getRequirementKey() == entry->getRequirementKey())
+ {
+ requirementVal = reqEntry->getRequirementVal();
+ break;
+ }
+ }
+ }
+ SLANG_ASSERT(requirementVal != nullptr);
+ IRFuncType* requirementFuncType = cast<IRFuncType>(requirementVal);
emitType(funcVal->getResultType());
m_writer->emit(" ");
m_writer->emit(_getWitnessTableWrapperFuncName(funcVal));
@@ -1630,23 +1645,20 @@ void CPPSourceEmitter::_emitWitnessTableWrappers()
// Emit parameter list.
{
bool isFirst = true;
- for (auto param : funcVal->getParams())
+ SLANG_ASSERT(funcVal->getParamCount() == requirementFuncType->getParamCount());
+ auto pp = funcVal->getParams().begin();
+ for (UInt i = 0; i < requirementFuncType->getParamCount(); ++i, ++pp)
{
- if (as<IRTypeType>(param->getFullType()))
+ auto paramType = requirementFuncType->getParamType(i);
+
+ if (as<IRTypeType>(paramType))
continue;
if (isFirst)
isFirst = false;
else
m_writer->emit(",");
-
- if (param->findDecoration<IRThisPointerDecoration>())
- {
- m_writer->emit("void* ");
- m_writer->emit(getName(param));
- continue;
- }
- emitSimpleFuncParamImpl(param);
+ emitParamType(paramType, getName(*pp));
}
}
m_writer->emit(")\n{\n");
@@ -1657,8 +1669,13 @@ void CPPSourceEmitter::_emitWitnessTableWrappers()
// Emit argument list.
{
bool isFirst = true;
- for (auto param : funcVal->getParams())
+ UInt paramIndex = 0;
+ for (auto defParamIter = funcVal->getParams().begin();
+ defParamIter!=funcVal->getParams().end();
+ ++defParamIter, ++paramIndex)
{
+ auto param = *defParamIter;
+ auto reqParamType = requirementFuncType->getParamType(paramIndex);
if (as<IRTypeType>(param->getFullType()))
continue;
@@ -1667,7 +1684,8 @@ void CPPSourceEmitter::_emitWitnessTableWrappers()
else
m_writer->emit(", ");
- if (param->findDecoration<IRThisPointerDecoration>())
+ if (reqParamType->op == kIROp_RawPointerType &&
+ param->getFullType()->op != kIROp_RawPointerType)
{
m_writer->emit("*static_cast<");
emitType(param->getFullType());
@@ -1779,13 +1797,7 @@ void CPPSourceEmitter::_maybeEmitWitnessTableTypeDefinition(
m_writer->emit(", ");
else
isFirstParam = false;
- auto thisDecor = funcVal->findDecoration<IRThisPointerDecoration>();
- if (thisDecor && cast<IRIntLit>(thisDecor->getOperand(0))->value.intVal == (IRIntegerValue)p)
- {
- m_writer->emit("void* param");
- m_writer->emit(p);
- continue;
- }
+
emitParamType(paramType, String("param") + String(p));
}
m_writer->emit(");\n");
diff --git a/source/slang/slang-ir-inst-defs.h b/source/slang/slang-ir-inst-defs.h
index 94c29371a..85c489528 100644
--- a/source/slang/slang-ir-inst-defs.h
+++ b/source/slang/slang-ir-inst-defs.h
@@ -167,6 +167,7 @@ INST(Nop, nop, 0, 0)
INST(StructType, struct, 0, PARENT)
INST(InterfaceType, interface, 0, 0)
INST(AssociatedType, associated_type, 0, 0)
+INST(ThisType, this_type, 0, 0)
// A TypeType-typed IRValue represents a IRType.
// It is used to represent a type parameter/argument in a generics.
@@ -510,14 +511,6 @@ INST(HighLevelDeclDecoration, highLevelDecl, 1, 0)
INST(BindExistentialSlotsDecoration, bindExistentialSlots, 0, 0)
-
- /// A `[this_ptr]` decoration marks a function parameter that serves as `this` pointer.
- /// `[this_ptr]` decoration is also used to mark an `IRFunc` as a non-static function.
- /// The argument is an integer value that represents the index of the `this` parameter,
- /// which is always 0.
- INST(ThisPointerDecoration, this_ptr, 1, 0)
-
-
/// A `[format(f)]` decoration specifies that the format of an image should be `f`
INST(FormatDecoration, format, 1, 0)
diff --git a/source/slang/slang-ir-insts.h b/source/slang/slang-ir-insts.h
index fcefa8b26..f3a0688a7 100644
--- a/source/slang/slang-ir-insts.h
+++ b/source/slang/slang-ir-insts.h
@@ -165,8 +165,6 @@ IR_SIMPLE_DECORATION(VulkanCallablePayloadDecoration)
/// vulkan hit attributes, and should have a location assigned
/// to it.
IR_SIMPLE_DECORATION(VulkanHitAttributesDecoration)
-IR_SIMPLE_DECORATION(ThisPointerDecoration)
-
struct IRRequireGLSLVersionDecoration : IRDecoration
{
@@ -1432,6 +1430,11 @@ struct IRWitnessTable : IRInst
return IRInstList<IRWitnessTableEntry>(getChildren());
}
+ IRInst* getConformanceType()
+ {
+ return getOperand(0);
+ }
+
IR_LEAF_ISA(WitnessTable)
};
@@ -1572,6 +1575,7 @@ struct IRBuilder
IRBasicType* getIntType();
IRStringType* getStringType();
IRAssociatedType* getAssociatedType();
+ IRThisType* getThisType();
IRRawPointerType* getRawPointerType();
@@ -2167,11 +2171,6 @@ struct IRBuilder
addDecoration(value, kIROp_LoopControlDecoration, getIntValue(getIntType(), IRIntegerValue(mode)));
}
- void addThisPointerDecoration(IRInst* value, int paramIndex)
- {
- addDecoration(value, kIROp_ThisPointerDecoration, getIntValue(getIntType(), paramIndex));
- }
-
void addSemanticDecoration(IRInst* value, UnownedStringSlice const& text, int index = 0)
{
addDecoration(value, kIROp_SemanticDecoration, getStringValue(text), getIntValue(getIntType(), index));
diff --git a/source/slang/slang-ir-lower-generics.cpp b/source/slang/slang-ir-lower-generics.cpp
index c374f45fa..774836e29 100644
--- a/source/slang/slang-ir-lower-generics.cpp
+++ b/source/slang/slang-ir-lower-generics.cpp
@@ -52,6 +52,7 @@ namespace Slang
return true;
switch (typeInst->op)
{
+ case kIROp_ThisType:
case kIROp_AssociatedType:
case kIROp_InterfaceType:
return true;
diff --git a/source/slang/slang-ir.cpp b/source/slang/slang-ir.cpp
index 8cf7ab171..ef5ecb959 100644
--- a/source/slang/slang-ir.cpp
+++ b/source/slang/slang-ir.cpp
@@ -2200,6 +2200,11 @@ namespace Slang
return (IRAssociatedType*)getType(kIROp_AssociatedType);
}
+ IRThisType* IRBuilder::getThisType()
+ {
+ return (IRThisType*)getType(kIROp_ThisType);
+ }
+
IRRawPointerType* IRBuilder::getRawPointerType()
{
return (IRRawPointerType*)getType(kIROp_RawPointerType);
diff --git a/source/slang/slang-ir.h b/source/slang/slang-ir.h
index 54658980d..dadcce386 100644
--- a/source/slang/slang-ir.h
+++ b/source/slang/slang-ir.h
@@ -1200,6 +1200,11 @@ struct IRAssociatedType : IRType
IR_LEAF_ISA(AssociatedType)
};
+struct IRThisType : IRType
+{
+ IR_LEAF_ISA(ThisType)
+};
+
struct IRInterfaceRequirementEntry : IRInst
{
IRInst* getRequirementKey() { return getOperand(0); }
diff --git a/source/slang/slang-lower-to-ir.cpp b/source/slang/slang-lower-to-ir.cpp
index 5bd983cab..ebc2e1b74 100644
--- a/source/slang/slang-lower-to-ir.cpp
+++ b/source/slang/slang-lower-to-ir.cpp
@@ -380,6 +380,9 @@ struct IRGenContext
// might be insufficient.
LoweredValInfo thisVal;
+ // The IRType value to lower into for `ThisType`.
+ IRInst* thisType = nullptr;
+
explicit IRGenContext(SharedIRGenContext* inShared, ASTBuilder* inAstBuilder)
: shared(inShared)
, astBuilder(inAstBuilder)
@@ -1582,6 +1585,8 @@ struct ValLoweringVisitor : ValVisitor<ValLoweringVisitor, LoweredValInfo, Lower
//
// For now we punt and emit the `ThisType` of an interface `IFoo` as `IFoo`.
//
+ if (context->thisType != nullptr)
+ return LoweredValInfo::simple(context->thisType);
return emitDeclRef(context, type->interfaceDeclRef, getBuilder()->getTypeKind());
}
@@ -5068,6 +5073,8 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo>
subContextStorage.irBuilder = &subBuilderStorage;
subContextStorage.env = &subEnvStorage;
+
+ subContextStorage.thisType = outerContext->thisType;
}
IRBuilder* getBuilder() { return &subBuilderStorage; }
@@ -5292,12 +5299,38 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo>
NestedContext nestedContext(this);
auto subBuilder = nestedContext.getBuilder();
auto subContext = nestedContext.getContext();
+
+ // Emit any generics that should wrap the actual type.
+ auto outerGeneric = emitOuterGenerics(subContext, decl, decl);
+
+ // Setup subContext for proper lowering `ThisType`, associated types and
+ // the interface decl's self reference.
+ subContext->thisType = getBuilder()->getThisType();
+ // Create a temporary IR value for self references, this will be replaced
+ // by actual interface type after we create the actual interface type.
+ auto temporarySelf = subBuilder->createIntrinsicInst(nullptr, kIROp_undefined, 0, nullptr);
+ subContext->env->mapDeclToValue[decl] = LoweredValInfo::simple(temporarySelf);
+ for (auto member : decl->members)
+ {
+ if (as<AssocTypeDecl>(member))
+ {
+ subContext->env->mapDeclToValue[member] = getBuilder()->getAssociatedType();
+ }
+ }
+
List<IRInterfaceRequirementEntry*> requirementEntries;
for (auto requirementDecl : decl->members)
{
auto key = getInterfaceRequirementKey(requirementDecl);
- auto entry = subBuilder->createInterfaceRequirementEntry(key, nullptr);
+ IRInst* requirementVal = lowerDecl(subContext, requirementDecl).val;
+ if (requirementVal)
+ {
+ auto reqType = requirementVal->getFullType();
+ requirementVal->removeAndDeallocate();
+ requirementVal = reqType;
+ }
+ auto entry = subBuilder->createInterfaceRequirementEntry(key, requirementVal);
requirementEntries.add(entry);
// As a special case, any type constraints placed
// on an associated type will *also* need to be turned
@@ -5312,11 +5345,9 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo>
getBuilder()->getWitnessTableType(lowerType(context, constraintDecl->getSup().type))));
}
}
+ context->env->mapDeclToValue[requirementDecl] = LoweredValInfo::simple(entry);
}
- // Emit any generics that should wrap the actual type.
- auto outerGeneric = emitOuterGenerics(subContext, decl, decl);
-
IRInterfaceType* irInterface = subBuilder->createInterfaceType(
requirementEntries.getCount(),
reinterpret_cast<IRInst**>(requirementEntries.getBuffer()));
@@ -5330,8 +5361,12 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo>
addTargetIntrinsicDecorations(irInterface, decl);
-
- return LoweredValInfo::simple(finishOuterGenerics(subBuilder, irInterface, outerGeneric));
+ auto finalVal = finishOuterGenerics(subBuilder, irInterface, outerGeneric);
+ // Now we can replace all self references in the requirement types to the
+ // actual interface type we generated.
+ temporarySelf->replaceUsesWith(finalVal);
+ temporarySelf->removeAndDeallocate();
+ return LoweredValInfo::simple(finalVal);
}
LoweredValInfo visitEnumCaseDecl(EnumCaseDecl* decl)
@@ -6133,8 +6168,6 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo>
paramTypes.getBuffer(),
irResultType);
- if (parameterLists.params.getCount() && parameterLists.params[0].isThisParam)
- builder->addThisPointerDecoration(irFuncType, 0);
return irFuncType;
}
@@ -6326,7 +6359,6 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo>
if (paramInfo.isThisParam)
{
subContext->thisVal = paramVal;
- subBuilder->addThisPointerDecoration(irParam, (int)(paramTypeIndex - 1));
}
}
@@ -6548,44 +6580,9 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo>
genericVal->setFullType((IRType*)funcType);
}
- maybeAssociateToInterfaceType(decl, finalVal);
-
return LoweredValInfo::simple(finalVal);
}
- void maybeAssociateToInterfaceType(Decl* decl, IRInst* irFuncVal)
- {
- auto parent = decl->parentDecl;
- InterfaceDecl* interfaceDecl = nullptr;
- while (parent)
- {
- interfaceDecl = as<InterfaceDecl>(parent);
- if (interfaceDecl) break;
- parent = parent->parentDecl;
- }
- if (!interfaceDecl)
- return;
- auto loweredVal = context->findLoweredDecl(interfaceDecl);
- if (!loweredVal)
- {
- return;
- }
- IRInst* irFuncType = irFuncVal->typeUse.get();
- auto irInterfaceType = cast<IRInterfaceType>(loweredVal->val);
- auto key = getInterfaceRequirementKey(decl);
- for (UInt i = 0; i < irInterfaceType->getOperandCount(); i++)
- {
- auto operand = cast<IRInterfaceRequirementEntry>(irInterfaceType->getOperand(i));
- if (operand->getRequirementKey() == key)
- {
- operand->setRequirementVal(irFuncType);
- return;
- }
- }
- SLANG_UNREACHABLE("associating interface function declaration:"
- "requirement not found in the interface type.");
- }
-
LoweredValInfo visitGenericDecl(GenericDecl * genDecl)
{
// TODO: Should this just always visit/lower the inner decl?