summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authorYong He <yonghe@outlook.com>2017-11-03 18:55:03 -0400
committerYong He <yonghe@outlook.com>2017-11-03 18:55:03 -0400
commit0a3656788473244b4760791c4129a4080a6631f6 (patch)
tree98f47426d4b4cf08f31416e9dfb32df0bebbc7c8 /source
parent38ec0e0976010aee2f68dba47563adba798cfcc3 (diff)
associatedtypes: generating almost correct HLSL, but is not calling correctly mangled function.
Diffstat (limited to 'source')
-rw-r--r--source/slang/check.cpp157
-rw-r--r--source/slang/emit.cpp5
-rw-r--r--source/slang/lower-to-ir.cpp7
-rw-r--r--source/slang/lower.cpp4
-rw-r--r--source/slang/slang.cpp1
-rw-r--r--source/slang/slang.natvis21
-rw-r--r--source/slang/syntax.cpp120
-rw-r--r--source/slang/syntax.h3
-rw-r--r--source/slang/type-defs.h32
9 files changed, 329 insertions, 21 deletions
diff --git a/source/slang/check.cpp b/source/slang/check.cpp
index 137b1c451..240ac2d05 100644
--- a/source/slang/check.cpp
+++ b/source/slang/check.cpp
@@ -148,13 +148,15 @@ namespace Slang
if (baseExpr)
{
RefPtr<Expr> expr;
-
+ DeclRef<Decl> *declRefOut;
if (baseExpr->type->As<TypeType>())
{
auto sexpr = new StaticMemberExpr();
sexpr->loc = loc;
sexpr->BaseExpression = baseExpr;
sexpr->name = declRef.GetName();
+ sexpr->declRef = declRef;
+ declRefOut = &sexpr->declRef;
expr = sexpr;
}
else
@@ -164,24 +166,88 @@ namespace Slang
sexpr->BaseExpression = baseExpr;
sexpr->name = declRef.GetName();
sexpr->declRef = declRef;
+ declRefOut = &sexpr->declRef;
expr = sexpr;
}
if (auto assocTypeDecl = declRef.As<AssocTypeDecl>())
{
RefPtr<ThisTypeSubstitution> subst = new ThisTypeSubstitution();
- subst->sourceType = baseExpr->type.type;
+ auto baseDeclRefType = baseExpr->type.type.As<DeclRefType>();
+ if (baseDeclRefType && !baseDeclRefType->declRef.getDecl()->As<InterfaceDecl>())
+ {
+ // if base type is not an interface, insert a non-trivial this_type substitution
+ subst->sourceType = baseExpr->type.type;
+ }
+ else
+ {
+ // otherwise, insert a null this type substitution, indicating that "this_type" is currently a free variable
+ subst->sourceType = nullptr;
+ }
if (auto typeType = subst->sourceType.As<TypeType>())
subst->sourceType = typeType->type;
expr->type = GetTypeForDeclRef(DeclRef<AssocTypeDecl>(assocTypeDecl.getDecl(), subst));
+ declRefOut->substitutions = subst;
+ return expr;
}
else if (auto constraintDecl = declRef.As<GenericTypeConstraintDecl>())
{
- expr->type = baseExpr->type;
+ expr = baseExpr;
+ if (auto declRefExpr = expr.As<DeclRefExpr>())
+ declRefOut = &declRefExpr->declRef;
+ else
+ return expr;
+ RefPtr<DeclRefType> declRefType;
+ if (auto typeType = baseExpr->type.type.As<TypeType>())
+ declRefType = typeType->type->As<DeclRefType>();
+ else
+ declRefType = baseExpr->type.type.As<DeclRefType>();
+
+ if (declRefType)
+ {
+ RefPtr<ThisTypeSubstitution> subst = new ThisTypeSubstitution();
+ subst->sourceType = declRefType;
+ auto exprType = DeclRefType::Create(getSession(), DeclRef<Decl>(declRefType->declRef.decl, declRef.substitutions));
+ subst->outer = declRef.substitutions;
+ exprType->declRef.substitutions = subst;
+ declRefOut->substitutions = subst;
+ expr->type = exprType;
+ return expr;
+ }
}
- else
+ else if (auto callableDeclRef = declRef.As<CallableDecl>())
{
+ // propagate ThisTypeSubstitution
+ RefPtr<DeclRefType> declRefType;
+ if (auto typeType = baseExpr->type.type.As<TypeType>())
+ declRefType = typeType->type->As<DeclRefType>();
+ else
+ declRefType = baseExpr->type.type.As<DeclRefType>();
+ RefPtr<ThisTypeSubstitution> thisSubst;
+ if (declRefType)
+ {
+ auto subst = declRefType->declRef.substitutions;
+ while (subst)
+ {
+ thisSubst = subst.As<ThisTypeSubstitution>();
+ if (thisSubst)
+ {
+ break;
+ }
+ subst = subst->outer;
+ }
+ }
+ if (thisSubst)
+ {
+ auto newThisSubst = new ThisTypeSubstitution();
+ newThisSubst->sourceType = thisSubst->sourceType;
+ newThisSubst->outer = declRefType->declRef.substitutions;
+ declRef.substitutions = thisSubst;
+ }
expr->type = GetTypeForDeclRef(declRef);
+ *declRefOut = declRef;
}
+
+ expr->type = GetTypeForDeclRef(declRef);
return expr;
}
else
@@ -908,12 +974,36 @@ namespace Slang
}
//
-
-
if (auto toDeclRefType = toType->As<DeclRefType>())
{
auto toTypeDeclRef = toDeclRefType->declRef;
- if (auto interfaceDeclRef = toTypeDeclRef.As<InterfaceDecl>())
+ if (auto assocDeclRef = toTypeDeclRef.As<AssocTypeDecl>())
+ {
+ if (auto fromTypeDeclRefType = fromType->As<DeclRefType>())
+ {
+ if (auto thisSubst = assocDeclRef.substitutions.As<ThisTypeSubstitution>())
+ {
+ if (auto fromThisSubst = fromTypeDeclRefType->declRef.substitutions.As<ThisTypeSubstitution>())
+ {
+ if (!thisSubst->sourceType || !fromThisSubst->sourceType)
+ return true;
+ if (CanCoerce(thisSubst->sourceType.As<Type>(), fromThisSubst->sourceType.As<Type>(), outCost))
+ {
+ if (outCost)
+ *outCost = kConversionCost_CastToInterface;
+ if (outToExpr)
+ *outToExpr = fromExpr;
+ return true;
+ }
+ }
+ else
+ return true;
+ }
+ else
+ return true;
+ }
+ }
+ else if (auto interfaceDeclRef = toTypeDeclRef.As<InterfaceDecl>())
{
// Trying to convert to an interface type.
//
@@ -927,8 +1017,42 @@ namespace Slang
return true;
}
}
- }
+ else if (auto genParamDeclRef = toTypeDeclRef.As<GenericTypeParamDecl>())
+ {
+ // We need to enumerate the constraints placed on this type by its outer
+ // generic declaration, and see if any of them guarantees that we
+ // satisfy the given interface..
+ auto genericDeclRef = genParamDeclRef.GetParent().As<GenericDecl>();
+ SLANG_ASSERT(genericDeclRef);
+
+ for (auto constraintDeclRef : getMembersOfType<GenericTypeConstraintDecl>(genericDeclRef))
+ {
+ auto sub = GetSub(constraintDeclRef);
+ auto sup = GetSup(constraintDeclRef);
+ auto subDeclRef = sub->As<DeclRefType>();
+ if (!subDeclRef)
+ continue;
+ if (subDeclRef->declRef != genParamDeclRef)
+ continue;
+ auto supDeclRefType = sup->As<DeclRefType>();
+ if (supDeclRefType)
+ {
+ auto toInterfaceDeclRef = supDeclRefType->declRef.As<InterfaceDecl>();
+ if (DoesTypeConformToInterface(fromType, toInterfaceDeclRef))
+ {
+ if (outToExpr)
+ *outToExpr = CreateImplicitCastExpr(toType, fromExpr);
+ if (outCost)
+ *outCost = kConversionCost_CastToInterface;
+ return true;
+ }
+ }
+ }
+
+ }
+
+ }
// Look for an initializer/constructor declaration in the target type,
// which is marked as usable for implicit conversion, and which takes
// the source type as an argument.
@@ -1891,6 +2015,8 @@ namespace Slang
void visitFuncDecl(FuncDecl *functionNode)
{
+ if (functionNode->nameAndLoc.name->text == "test")
+ printf("break");
if (functionNode->IsChecked(DeclCheckState::Checked))
return;
@@ -4384,7 +4510,7 @@ namespace Slang
callExpr->FunctionExpr = baseExpr;
- callExpr->type = QualType(candidate.resultType);// QualType(baseExpr->type->As<FuncType>()->resultType);
+ callExpr->type = QualType(candidate.resultType);
// A call may yield an l-value, and we should take a look at the candidate to be sure
if(auto subscriptDeclRef = candidate.item.declRef.As<SubscriptDecl>())
@@ -4575,9 +4701,7 @@ namespace Slang
OverloadCandidate candidate;
candidate.flavor = OverloadCandidate::Flavor::Func;
candidate.item = item;
- auto baseExpr = ConstructLookupResultExpr(
- item, context.baseExpr, context.funcLoc);
- candidate.resultType = baseExpr->type->As<FuncType>()->resultType; // GetResultType(funcDeclRef);
+ candidate.resultType = GetResultType(funcDeclRef);
AddOverloadCandidate(context, candidate);
}
@@ -5739,6 +5863,9 @@ namespace Slang
RefPtr<Expr> visitInvokeExpr(InvokeExpr *expr)
{
+ if (auto mbrExpr = expr->FunctionExpr->As<MemberExpr>())
+ if (mbrExpr->name->text == "add")
+ printf("break");
// check the base expression first
expr->FunctionExpr = CheckExpr(expr->FunctionExpr);
@@ -6471,6 +6598,12 @@ namespace Slang
auto type = getFuncType(session, funcDeclRef);
return QualType(type);
}
+ else if (auto constraintDeclRef = declRef.As<GenericTypeConstraintDecl>())
+ {
+ auto type = DeclRefType::Create(session, constraintDeclRef);
+ *outTypeResult = type;
+ return QualType(getTypeType(type));
+ }
if( sink )
{
sink->diagnose(declRef, Diagnostics::unimplemented, "cannot form reference to this kind of declaration");
diff --git a/source/slang/emit.cpp b/source/slang/emit.cpp
index 2627e1f37..54788e33a 100644
--- a/source/slang/emit.cpp
+++ b/source/slang/emit.cpp
@@ -1195,6 +1195,11 @@ struct EmitVisitor
EmitDeclarator(declarator);
}
+ void visitThisType(ThisType* type, TypeEmitArg const&)
+ {
+ return;
+ }
+
void visitDeclRefType(DeclRefType* declRefType, TypeEmitArg const& arg)
{
auto declarator = arg.declarator;
diff --git a/source/slang/lower-to-ir.cpp b/source/slang/lower-to-ir.cpp
index 6099df1ed..7a3e9356a 100644
--- a/source/slang/lower-to-ir.cpp
+++ b/source/slang/lower-to-ir.cpp
@@ -881,6 +881,11 @@ struct ValLoweringVisitor : ValVisitor<ValLoweringVisitor, LoweredValInfo, Lower
}
}
+ LoweredTypeInfo visitThisType(ThisType* type)
+ {
+ return LoweredTypeInfo();
+ }
+
LoweredTypeInfo visitDeclRefType(DeclRefType* type)
{
// If the type in question comes from the module we are
@@ -2647,6 +2652,8 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo>
LoweredValInfo lowerFuncDecl(FunctionDeclBase* decl)
{
+ if (decl->getName()->text == "test")
+ printf("break");
// Collect the parameter lists we will use for our new function.
ParameterLists parameterLists;
collectParameterLists(decl, &parameterLists, kParameterListCollectMode_Default);
diff --git a/source/slang/lower.cpp b/source/slang/lower.cpp
index b8696df47..bdd041f71 100644
--- a/source/slang/lower.cpp
+++ b/source/slang/lower.cpp
@@ -765,6 +765,10 @@ struct LoweringVisitor
loweredDeclRef.As<Decl>());
}
+ RefPtr<Type> visitThisType(ThisType* type)
+ {
+ return type;
+ }
RefPtr<Type> visitNamedExpressionType(NamedExpressionType* type)
{
diff --git a/source/slang/slang.cpp b/source/slang/slang.cpp
index f1d1d6ba2..602a929b2 100644
--- a/source/slang/slang.cpp
+++ b/source/slang/slang.cpp
@@ -300,6 +300,7 @@ int CompileRequest::executeActionsInner()
// Generate initial IR for all the translation
// units, if we are in a mode where IR is called for.
generateIR();
+
if (mSink.GetErrorCount() != 0)
return 1;
diff --git a/source/slang/slang.natvis b/source/slang/slang.natvis
index 7e6fd3753..357251dcd 100644
--- a/source/slang/slang.natvis
+++ b/source/slang/slang.natvis
@@ -35,4 +35,25 @@
<Type Name="Slang::NameLoc">
<DisplayString>{{name={(char*)((*name).text.buffer.pointer+1), s} loc={loc.raw}}}</DisplayString>
</Type>
+
+ <Type Name="Slang::IRInst">
+ <DisplayString>{{{op}}}</DisplayString>
+ <Expand>
+ <Item Name="[OpCode]">op</Item>
+ <Item Name="[ArgCount]">argCount</Item>
+ <ArrayItems>
+ <Size>argCount</Size>
+ <ValuePointer>(IRUse*)(this + 1)</ValuePointer>
+ </ArrayItems>
+ </Expand>
+ </Type>
+ <Type Name="Slang::IRBlock">
+ <Expand>
+ <LinkedListItems>
+ <HeadPointer>firstInst</HeadPointer>
+ <NextPointer>(Slang::IRInst*)next</NextPointer>
+ <ValueNode>this</ValueNode>
+ </LinkedListItems>
+ </Expand>
+ </Type>
</AutoVisualizer> \ No newline at end of file
diff --git a/source/slang/syntax.cpp b/source/slang/syntax.cpp
index a3a5fdcb6..2f3368f4c 100644
--- a/source/slang/syntax.cpp
+++ b/source/slang/syntax.cpp
@@ -376,6 +376,85 @@ void Type::accept(IValVisitor* visitor, void* extra)
(int)(typeid(this).hash_code()));
}
+ // ThisType
+
+ String ThisType::ToString()
+ {
+ return "<this_type>";
+ }
+
+ int ThisType::GetHashCode()
+ {
+ return 0;
+ }
+
+ bool ThisType::EqualsImpl(Type * type)
+ {
+ return true;
+ }
+
+ Type* ThisType::CreateCanonicalType()
+ {
+ // A declaration reference is already canonical
+ return this;
+ }
+
+ RefPtr<Val> ThisType::SubstituteImpl(Substitutions* subst, int* ioDiff)
+ {
+ while (subst)
+ {
+ if (auto thisTypeSubst = dynamic_cast<ThisTypeSubstitution*>(subst))
+ {
+ return thisTypeSubst->sourceType;
+ }
+ subst = subst->outer;
+ }
+ return this;
+ }
+
+ // MemberType
+ /*
+ String MemberType::ToString()
+ {
+ return objectType->ToString() + "::" + declRef.toString();
+ }
+
+ int MemberType::GetHashCode()
+ {
+ return combineHash(objectType->GetHashCode(), declRef.GetHashCode());
+ }
+
+ bool MemberType::EqualsImpl(Type * type)
+ {
+ if (auto memberType = dynamic_cast<MemberType*>(type))
+ return objectType->Equals(memberType->objectType.Ptr()) && declRef.Equals(memberType->declRef);
+ return false;
+ }
+
+ Type* MemberType::CreateCanonicalType()
+ {
+ if (auto declRefType = objectType->As<DeclRefType>())
+ {
+ if (auto aggDeclRef = declRefType->declRef.As<AggTypeDecl>())
+ {
+ Decl* targetDecl = nullptr;
+ if (aggDeclRef.getDecl()->memberDictionary.TryGetValue(declRef.getDecl()->nameAndLoc.name, targetDecl))
+ {
+ if (auto typeDefDecl = dynamic_cast<TypeDefDecl*>(targetDecl))
+ return typeDefDecl->type.type;
+ else
+ return DeclRefType::Create(getSession(), DeclRef<Decl>(targetDecl, aggDeclRef.substitutions));
+ }
+ }
+ }
+ return this;
+ }
+
+ RefPtr<Val> MemberType::SubstituteImpl(Substitutions* subst, int* ioDiff)
+ {
+ return this;
+ }
+ */
// DeclRefType
String DeclRefType::ToString()
@@ -451,16 +530,21 @@ void Type::accept(IValVisitor* visitor, void* extra)
// we want to replace it with the actual associated type
else if (auto assocTypeDecl = dynamic_cast<AssocTypeDecl*>(declRef.getDecl()))
{
- // search for a substitution that might apply to us
- for (auto s = subst; s; s = s->outer.Ptr())
+ auto newSubst = declRef.substitutions->SubstituteImpl(subst, ioDiff);
+ if (auto thisTypeSubst = newSubst.As<ThisTypeSubstitution>())
{
- if (auto thisTypeSubst = dynamic_cast<ThisTypeSubstitution*>(s))
+ if (thisTypeSubst->sourceType)
{
if (auto aggTypeDeclRef = thisTypeSubst->sourceType.As<DeclRefType>()->declRef.As<AggTypeDecl>())
{
Decl * targetType = nullptr;
if (aggTypeDeclRef.getDecl()->memberDictionary.TryGetValue(assocTypeDecl->getName(), targetType))
- return DeclRefType::Create(this->getSession(), DeclRef<Decl>(targetType, aggTypeDeclRef.substitutions));
+ {
+ if (auto typeDefDecl = dynamic_cast<TypeDefDecl*>(targetType))
+ return typeDefDecl->type.type;
+ else
+ return DeclRefType::Create(getSession(), DeclRef<Decl>(targetType, aggTypeDeclRef.substitutions));
+ }
}
}
}
@@ -1142,9 +1226,27 @@ void Type::accept(IValVisitor* visitor, void* extra)
if (!this) return nullptr;
int diff = 0;
- auto outerSubst = outer->SubstituteImpl(subst, &diff);
-
- auto newSourceType = sourceType->SubstituteImpl(subst, ioDiff);
+ RefPtr<Substitutions> outerSubst;
+ if (outer)
+ outerSubst = outer->SubstituteImpl(subst, &diff);
+ RefPtr<Val> newSourceType;
+ if (sourceType)
+ newSourceType = sourceType->SubstituteImpl(subst, &diff);
+ else
+ {
+ // this_type is a free variable, use this_type from subst
+ auto psubst = subst;
+ while (psubst)
+ {
+ if (auto pthisSubst = dynamic_cast<ThisTypeSubstitution*>(subst))
+ {
+ diff++;
+ newSourceType = pthisSubst->sourceType;
+ break;
+ }
+ psubst = psubst->outer;
+ }
+ }
if (!diff) return this;
(*ioDiff)++;
@@ -1162,7 +1264,9 @@ void Type::accept(IValVisitor* visitor, void* extra)
auto thisSubst = dynamic_cast<ThisTypeSubstitution*>(subst);
if (!thisSubst)
return false;
- if (!thisSubst->sourceType->EqualsVal(sourceType))
+ if (!sourceType && thisSubst->sourceType || sourceType && !thisSubst->sourceType)
+ return false;
+ if (thisSubst->sourceType && !thisSubst->sourceType->EqualsVal(sourceType))
return false;
if (!outer->Equals(subst->outer.Ptr()))
return false;
diff --git a/source/slang/syntax.h b/source/slang/syntax.h
index 0b5a38631..cf75b5624 100644
--- a/source/slang/syntax.h
+++ b/source/slang/syntax.h
@@ -439,6 +439,7 @@ namespace Slang
// Apply substitutions to this declaration reference
DeclRefBase SubstituteImpl(Substitutions* subst, int* ioDiff);
+
// Check if this is an equivalent declaration reference to another
bool Equals(DeclRefBase const& declRef) const;
bool operator == (const DeclRefBase& other) const
@@ -1154,7 +1155,7 @@ namespace Slang
RefPtr<Substitutions> createDefaultSubstitutions(
Session* session,
Decl* decl);
-
+
} // namespace Slang
#endif \ No newline at end of file
diff --git a/source/slang/type-defs.h b/source/slang/type-defs.h
index 60f519c82..7eda5b5ce 100644
--- a/source/slang/type-defs.h
+++ b/source/slang/type-defs.h
@@ -55,6 +55,38 @@ protected:
)
END_SYNTAX_CLASS()
+SYNTAX_CLASS(ThisType, Type)
+RAW(
+ virtual String ToString() override;
+ virtual RefPtr<Val> SubstituteImpl(Substitutions* subst, int* ioDiff) override;
+
+ ThisType()
+ {}
+ protected:
+ virtual int GetHashCode() override;
+ virtual bool EqualsImpl(Type * type) override;
+ virtual Type* CreateCanonicalType() override;
+ )
+END_SYNTAX_CLASS()
+
+/*
+SYNTAX_CLASS(MemberType, Type)
+ FIELD(RefPtr<Type>, objectType)
+ DECL_FIELD(DeclRef<Decl>, declRef)
+ RAW(
+ virtual String ToString() override;
+ virtual RefPtr<Val> SubstituteImpl(Substitutions* subst, int* ioDiff) override;
+
+ MemberType()
+ {}
+ protected:
+ virtual int GetHashCode() override;
+ virtual bool EqualsImpl(Type * type) override;
+ virtual Type* CreateCanonicalType() override;
+ )
+END_SYNTAX_CLASS()
+*/
+
// A type that takes the form of a reference to some declaration
SYNTAX_CLASS(DeclRefType, Type)
DECL_FIELD(DeclRef<Decl>, declRef)