diff options
| author | Yong He <yonghe@outlook.com> | 2017-11-03 18:55:03 -0400 |
|---|---|---|
| committer | Yong He <yonghe@outlook.com> | 2017-11-03 18:55:03 -0400 |
| commit | 0a3656788473244b4760791c4129a4080a6631f6 (patch) | |
| tree | 98f47426d4b4cf08f31416e9dfb32df0bebbc7c8 /source | |
| parent | 38ec0e0976010aee2f68dba47563adba798cfcc3 (diff) | |
associatedtypes: generating almost correct HLSL, but is not calling correctly mangled function.
Diffstat (limited to 'source')
| -rw-r--r-- | source/slang/check.cpp | 157 | ||||
| -rw-r--r-- | source/slang/emit.cpp | 5 | ||||
| -rw-r--r-- | source/slang/lower-to-ir.cpp | 7 | ||||
| -rw-r--r-- | source/slang/lower.cpp | 4 | ||||
| -rw-r--r-- | source/slang/slang.cpp | 1 | ||||
| -rw-r--r-- | source/slang/slang.natvis | 21 | ||||
| -rw-r--r-- | source/slang/syntax.cpp | 120 | ||||
| -rw-r--r-- | source/slang/syntax.h | 3 | ||||
| -rw-r--r-- | source/slang/type-defs.h | 32 |
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, ¶meterLists, 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) |
