From 093bf1eb9149ba82258b5a5a159b2f54263b17c2 Mon Sep 17 00:00:00 2001 From: Yong He Date: Tue, 31 Oct 2017 11:12:08 -0400 Subject: work in-progress: type checking associated types --- source/slang/check.cpp | 96 +++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 88 insertions(+), 8 deletions(-) (limited to 'source/slang/check.cpp') diff --git a/source/slang/check.cpp b/source/slang/check.cpp index 0c35c4bf4..fe7498d86 100644 --- a/source/slang/check.cpp +++ b/source/slang/check.cpp @@ -1538,7 +1538,48 @@ namespace Slang requiredInitDecl); } } + else if (auto subStructTypeDecl = dynamic_cast(memberDecl)) + { + // this is a sub type (e.g. nested struct declaration) in an aggregate type + // check if this sub type declaration satisfies the constraints defined by the associated type + if (auto requiredTypeDecl = requiredMemberDeclRef.As()) + { + bool conformance = true; + for (auto & inheritanceDecl : requiredTypeDecl.getDecl()->getMembersOfType()) + { + conformance = conformance && checkConformance(subStructTypeDecl, inheritanceDecl.Ptr()); + } + return conformance; + } + } + else if (auto typedefDecl = dynamic_cast(memberDecl)) + { + // this is a type-def decl in an aggregate type + // check if the specified type satisfies the constraints defined by the associated type + if (auto requiredTypeDecl = requiredMemberDeclRef.As()) + { + auto constraintList = requiredTypeDecl.getDecl()->getMembersOfType(); + if (constraintList.Count()) + { + auto declRefType = typedefDecl->type->AsDeclRefType(); + if (!declRefType) + return false; + auto subStructTypeDecl = declRefType->declRef.getDecl()->As(); + //TODO: What do we do if type is a generic specialization? + // i.e. if the struct defines typedef Generic T; + // how to check if T satisfies the associatedtype constraints? + // the code below will only work when T is defined to be a simple aggregated type (no generics). + bool conformance = true; + for (auto & inheritanceDecl : constraintList) + { + conformance = conformance && checkConformance(subStructTypeDecl, inheritanceDecl.Ptr()); + } + return conformance; + } + return true; + } + } // Default: just assume that thing aren't being satisfied. return false; } @@ -1623,11 +1664,13 @@ namespace Slang // declares conformance to the interface `interfaceDeclRef`, // (via the given `inheritanceDecl`) actually provides // members to satisfy all the requirements in the interface. - void checkInterfaceConformance( + bool checkInterfaceConformance( AggTypeDecl* typeDecl, InheritanceDecl* inheritanceDecl, DeclRef interfaceDeclRef) { + bool result = true; + // We need to check the declaration of the interface // before we can check that we conform to it. EnsureDecl(interfaceDeclRef.getDecl()); @@ -1654,7 +1697,7 @@ namespace Slang // to the inherited interface. // // TODO: we *really* need a linearization step here!!!! - checkConformanceToType( + result = result && checkConformanceToType( typeDecl, inheritanceDecl, getBaseType(requiredInheritanceDeclRef)); @@ -1670,16 +1713,20 @@ namespace Slang requiredMemberDeclRef); if (!conformanceWitness) + { + result = false; continue; + } // Store that witness into a table stored on the `inheritnaceDecl` // so that it can be used for downstream code generation. inheritanceDecl->requirementWitnesses.Add(requiredMemberDeclRef, conformanceWitness); } + return result; } - void checkConformanceToType( + bool checkConformanceToType( AggTypeDecl* typeDecl, InheritanceDecl* inheritanceDecl, Type* baseType) @@ -1692,29 +1739,29 @@ namespace Slang // The type is stating that it conforms to an interface. // We need to check that it provides all of the members // required by that interface. - checkInterfaceConformance( + return checkInterfaceConformance( typeDecl, inheritanceDecl, baseInterfaceDeclRef); - return; } } getSink()->diagnose(inheritanceDecl, Diagnostics::unimplemented, "type not supported for inheritance"); + return false; } // Check that the type declaration `typeDecl`, which // declares that it inherits from another type via // `inheritanceDecl` actually does what it needs to // for that inheritance to be valid. - void checkConformance( + bool checkConformance( AggTypeDecl* typeDecl, InheritanceDecl* inheritanceDecl) { // Look at the type being inherited from, and validate // appropriately. auto baseType = inheritanceDecl->base.type; - checkConformanceToType(typeDecl, inheritanceDecl, baseType); + return checkConformanceToType(typeDecl, inheritanceDecl, baseType); } void visitAggTypeDecl(AggTypeDecl* decl) @@ -1758,6 +1805,11 @@ namespace Slang // Don't check that an interface conforms to the // things it inherits from. } + else if (auto assocTypeDecl = dynamic_cast(decl)) + { + // Don't check that an associated type decl conforms to the + // things it inherits from. + } else { // For non-interface types we need to check conformance. @@ -1794,6 +1846,24 @@ namespace Slang decl->SetCheckState(DeclCheckState::Checked); } + void visitAssocTypeDecl(AssocTypeDecl* decl) + { + if (decl->IsChecked(DeclCheckState::Checked)) return; + decl->SetCheckState(DeclCheckState::CheckedHeader); + + // assoctype only allowed in an interface + auto interfaceDecl = decl->ParentDecl->As(); + if (!interfaceDecl) + getSink()->diagnose(decl, Slang::Diagnostics::assocTypeInInterfaceOnly); + + // Now check all of the member declarations. + for (auto member : decl->Members) + { + checkDecl(member); + } + decl->SetCheckState(DeclCheckState::Checked); + } + void checkStmt(Stmt* stmt) { if (!stmt) return; @@ -5647,8 +5717,13 @@ namespace Slang RefPtr visitInvokeExpr(InvokeExpr *expr) { + if (auto appExpr = expr->FunctionExpr->As()) + if (auto varExpr = appExpr->FunctionExpr->As()) + if (varExpr->name->text == "test") + printf("break"); // check the base expression first expr->FunctionExpr = CheckExpr(expr->FunctionExpr); + // Next check the argument expressions for (auto & arg : expr->Arguments) @@ -6386,7 +6461,12 @@ namespace Slang auto type = getFuncType(session, funcDeclRef); return QualType(type); } - + else if (auto assocTypeDeclRef = declRef.As()) + { + auto type = DeclRefType::Create(session, assocTypeDeclRef); + *outTypeResult = type; + return QualType(getTypeType(type)); + } if( sink ) { sink->diagnose(declRef, Diagnostics::unimplemented, "cannot form reference to this kind of declaration"); -- cgit v1.2.3 From 134354c68768c0e3530c02678e12cb02f5646e8a Mon Sep 17 00:00:00 2001 From: Yong He Date: Wed, 1 Nov 2017 13:16:26 -0400 Subject: Adding support for associated types. --- source/slang/check.cpp | 83 ++++++++++----- source/slang/emit.cpp | 6 +- source/slang/ir-insts.h | 3 +- source/slang/ir.cpp | 17 +++- source/slang/lower-to-ir.cpp | 8 +- source/slang/lower.cpp | 7 ++ source/slang/mangle.cpp | 4 + source/slang/syntax.cpp | 118 +++++++++++++++++++++- source/slang/type-defs.h | 33 +++++- tests/compute/assoctype-complex.slang | 44 ++++++++ tests/compute/assoctype-simple.slang | 2 +- tests/compute/assoctype-simple.slang.expected.txt | 4 + tools/render-test/render-d3d11.cpp | 3 +- 13 files changed, 294 insertions(+), 38 deletions(-) create mode 100644 tests/compute/assoctype-complex.slang create mode 100644 tests/compute/assoctype-simple.slang.expected.txt (limited to 'source/slang/check.cpp') diff --git a/source/slang/check.cpp b/source/slang/check.cpp index fe7498d86..2f4ed2ce8 100644 --- a/source/slang/check.cpp +++ b/source/slang/check.cpp @@ -147,26 +147,64 @@ namespace Slang { if (baseExpr) { + RefPtr expr; + if (baseExpr->type->As()) { - auto expr = new StaticMemberExpr(); - expr->loc = loc; - expr->BaseExpression = baseExpr; - expr->name = declRef.GetName(); - expr->type = GetTypeForDeclRef(declRef); - expr->declRef = declRef; - return expr; + auto sexpr = new StaticMemberExpr(); + sexpr->loc = loc; + sexpr->BaseExpression = baseExpr; + sexpr->name = declRef.GetName(); + sexpr->type = GetTypeForDeclRef(declRef); + sexpr->declRef = declRef; + expr = sexpr; } else { - auto expr = new MemberExpr(); - expr->loc = loc; - expr->BaseExpression = baseExpr; - expr->name = declRef.GetName(); - expr->type = GetTypeForDeclRef(declRef); - expr->declRef = declRef; - return expr; + auto sexpr = new MemberExpr(); + sexpr->loc = loc; + sexpr->BaseExpression = baseExpr; + sexpr->name = declRef.GetName(); + sexpr->type = GetTypeForDeclRef(declRef); + sexpr->declRef = declRef; + expr = sexpr; + } + if (auto assocTypeDeclRef = declRef.As()) + { + if (auto genConstraintType = baseExpr->type->As()) + { + // if this is a reference from a generic parameter, we need to generate a AssocTypeDeclRefType type. + // for example, if we have an expression T.U where T:ISimple, and U is an associated type defined in ISimple. + // then this expression should evaluate to AssocTypeDeclRefType(T, U). + auto assocTypeDeclType = new AssocTypeDeclRefType(); + assocTypeDeclType->declRef = assocTypeDeclRef; + assocTypeDeclType->sourceType = genConstraintType->subType; + assocTypeDeclType->setSession(getSession()); + expr->type = QualType(getTypeType(assocTypeDeclType)); + } } + else if (auto funcDeclRef = declRef.As()) + { + if (auto genConstraintType = baseExpr->type->As()) + { + // if this is call expression, propagate the source associated type to the result type + auto funcType = expr->type->As(); + if (auto assocRsType = funcType->resultType.As()) + { + RefPtr newFuncType = new FuncType(); + newFuncType->paramTypes = funcType->paramTypes; + RefPtr newRsType = new AssocTypeDeclRefType(); + newRsType->declRef = assocRsType->declRef; + newRsType->sourceType = genConstraintType->subType; + newRsType->setSession(getSession()); + newFuncType->resultType = newRsType; + newFuncType->setSession(funcType->getSession()); + expr->type = QualType(newFuncType); + } + + } + } + return expr; } else { @@ -1878,7 +1916,6 @@ namespace Slang VisitFunctionDeclaration(functionNode); // TODO: This should really onlye set "checked header" functionNode->SetCheckState(DeclCheckState::Checked); - // TODO: should put the checking of the body onto a "work list" // to avoid recursion here. if (functionNode->Body) @@ -2309,7 +2346,6 @@ namespace Slang { if (functionNode->IsChecked(DeclCheckState::CheckedHeader)) return; functionNode->SetCheckState(DeclCheckState::CheckingHeader); - this->function = functionNode; auto returnType = CheckProperType(functionNode->ReturnType); functionNode->ReturnType = returnType; @@ -4366,7 +4402,7 @@ namespace Slang callExpr->FunctionExpr = baseExpr; - callExpr->type = QualType(candidate.resultType); + callExpr->type = QualType(candidate.resultType);// QualType(baseExpr->type->As()->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()) @@ -4557,7 +4593,9 @@ namespace Slang OverloadCandidate candidate; candidate.flavor = OverloadCandidate::Flavor::Func; candidate.item = item; - candidate.resultType = GetResultType(funcDeclRef); + auto baseExpr = ConstructLookupResultExpr( + item, context.baseExpr, context.funcLoc); + candidate.resultType = baseExpr->type->As()->resultType; // GetResultType(funcDeclRef); AddOverloadCandidate(context, candidate); } @@ -5717,10 +5755,6 @@ namespace Slang RefPtr visitInvokeExpr(InvokeExpr *expr) { - if (auto appExpr = expr->FunctionExpr->As()) - if (auto varExpr = appExpr->FunctionExpr->As()) - if (varExpr->name->text == "test") - printf("break"); // check the base expression first expr->FunctionExpr = CheckExpr(expr->FunctionExpr); @@ -6453,7 +6487,7 @@ namespace Slang // When we access a constraint or an inheritance decl (as a member), // we are conceptually performing a "cast" to the given super-type, // with the declaration showing that such a cast is legal. - auto type = GetSup(constraintDeclRef); + auto type = new GenericConstraintDeclRefType(session, GetSub(constraintDeclRef), GetSup(constraintDeclRef)); return QualType(type); } else if (auto funcDeclRef = declRef.As()) @@ -6463,7 +6497,8 @@ namespace Slang } else if (auto assocTypeDeclRef = declRef.As()) { - auto type = DeclRefType::Create(session, assocTypeDeclRef); + auto type = new AssocTypeDeclRefType(assocTypeDeclRef); + type->setSession(session); *outTypeResult = type; return QualType(getTypeType(type)); } diff --git a/source/slang/emit.cpp b/source/slang/emit.cpp index 3454a3f85..9caad2e1a 100644 --- a/source/slang/emit.cpp +++ b/source/slang/emit.cpp @@ -1054,7 +1054,11 @@ struct EmitVisitor void visitAssocTypeDeclRefType(AssocTypeDeclRefType* /*type*/, TypeEmitArg const& /*arg*/) { - SLANG_UNREACHABLE("visitAssocTypeDeclRefType in EmitVisitor"); + //SLANG_UNREACHABLE("visitAssocTypeDeclRefType in EmitVisitor"); + } + void visitGenericConstraintDeclRefType(GenericConstraintDeclRefType* /*type*/, TypeEmitArg const& /*arg*/) + { + //SLANG_UNREACHABLE("visitGenericConstraintDeclRefType in EmitVisitor"); } void visitBasicExpressionType(BasicExpressionType* basicType, TypeEmitArg const& arg) diff --git a/source/slang/ir-insts.h b/source/slang/ir-insts.h index f7bcc2eb2..587fe3cd2 100644 --- a/source/slang/ir-insts.h +++ b/source/slang/ir-insts.h @@ -346,10 +346,9 @@ struct IRBuilder IRValue* getBoolValue(bool value); IRValue* getIntValue(IRType* type, IRIntegerValue value); IRValue* getFloatValue(IRType* type, IRFloatingPointValue value); - IRValue* getDeclRefVal( DeclRefBase const& declRef); - + IRValue* getTypeVal(IRType* type); // create an IR value that represents a type IRValue* emitSpecializeInst( IRType* type, IRValue* genericVal, diff --git a/source/slang/ir.cpp b/source/slang/ir.cpp index 5cc73a36b..84ab3d9a5 100644 --- a/source/slang/ir.cpp +++ b/source/slang/ir.cpp @@ -562,6 +562,16 @@ namespace Slang return irValue; } + IRValue * IRBuilder::getTypeVal(IRType * type) + { + auto irValue = createValue( + this, + kIROp_TypeType, + nullptr); + irValue->type = type; + return irValue; + } + IRValue* IRBuilder::emitSpecializeInst( Type* type, IRValue* genericVal, @@ -3061,7 +3071,12 @@ namespace Slang return builder->getDeclRefVal(declRef); } break; - + case kIROp_TypeType: + { + IRValue* od = (IRValue*)originalValue; + return builder->getTypeVal(od->type); + } + break; default: SLANG_UNEXPECTED("no value registered for IR value"); return nullptr; diff --git a/source/slang/lower-to-ir.cpp b/source/slang/lower-to-ir.cpp index 93b84ad31..998197279 100644 --- a/source/slang/lower-to-ir.cpp +++ b/source/slang/lower-to-ir.cpp @@ -2062,6 +2062,11 @@ struct DeclLoweringVisitor : DeclVisitor SLANG_UNIMPLEMENTED_X("decl catch-all"); } + LoweredValInfo visitTypeDefDecl(TypeDefDecl * decl) + { + return LoweredValInfo::simple(context->irBuilder->getTypeVal(decl->type.type)); + } + LoweredValInfo visitGenericTypeParamDecl(GenericTypeParamDecl* decl) { return LoweredValInfo(); @@ -2307,7 +2312,8 @@ struct DeclLoweringVisitor : DeclVisitor // For now, we don't have an IR-level representation // for the type itself. - return LoweredValInfo(); + return LoweredValInfo::simple(context->irBuilder->getTypeVal(DeclRefType::Create(context->getSession(), + DeclRef(decl, nullptr)))); } diff --git a/source/slang/lower.cpp b/source/slang/lower.cpp index 776a55530..b810d9643 100644 --- a/source/slang/lower.cpp +++ b/source/slang/lower.cpp @@ -779,6 +779,13 @@ struct LoweringVisitor translateDeclRef(DeclRef(type->declRef)).As()); } + RefPtr visitGenericConstraintDeclRefType(GenericConstraintDeclRefType* type) + { + // not supported by lowering + SLANG_UNREACHABLE("visitGenericConstraintDeclRefType in LowerVisitor"); + return nullptr; + } + RefPtr visitAssocTypeDeclRefType(AssocTypeDeclRefType* type) { // not supported by lowering diff --git a/source/slang/mangle.cpp b/source/slang/mangle.cpp index 63e54d065..cd90a0e41 100644 --- a/source/slang/mangle.cpp +++ b/source/slang/mangle.cpp @@ -117,6 +117,10 @@ namespace Slang { emitQualifiedName(context, declRefType->declRef); } + else if (auto assocTypeDeclRefType = dynamic_cast(type)) + { + emitQualifiedName(context, assocTypeDeclRefType->declRef); + } else { SLANG_UNEXPECTED("unimplemented case in mangling"); diff --git a/source/slang/syntax.cpp b/source/slang/syntax.cpp index 97f3cfb15..fd7fc0e14 100644 --- a/source/slang/syntax.cpp +++ b/source/slang/syntax.cpp @@ -959,15 +959,60 @@ void Type::accept(IValVisitor* visitor, void* extra) RefPtr AssocTypeDeclRefType::SubstituteImpl(Substitutions* subst, int* ioDiff) { - auto parentType = this->GetDeclRef().GetParent().SubstituteImpl(subst, ioDiff); - if (auto aggDeclRef = parentType.As()) + if (!sourceType) + return this; + if (auto parentDeclRefType = sourceType->As()) { - Decl* targetTypeDecl = nullptr; - if (aggDeclRef.getDecl()->memberDictionary.TryGetValue(this->GetDeclRef().decl->getName(), targetTypeDecl)) + auto parentDeclRef = parentDeclRefType->declRef; + DeclRef newParentDeclRef = parentDeclRef.As(); + // search for a substitution that might apply to us + for (auto s = subst; s; s = s->outer.Ptr()) { - return DeclRefType::Create(this->session, DeclRef(targetTypeDecl, parentType.substitutions)); + // the generic decl associated with the substitution list must be + // the generic decl that declared this parameter + auto genericDecl = s->genericDecl; + if (genericDecl != parentDeclRef.getDecl()->ParentDecl) + continue; + int index = 0; + for (auto m : genericDecl->Members) + { + if (m.Ptr() == parentDeclRef.getDecl()) + { + // We've found it, so return the corresponding specialization argument + (*ioDiff)++; + if (auto declRef = s->args[index].As()) + { + newParentDeclRef = (*declRef).declRef.As(); + goto searchEnd; + } + } + else if (auto typeParam = m.As()) + { + index++; + } + else if (auto valParam = m.As()) + { + index++; + } + else + { + } + } + } + searchEnd: + if (newParentDeclRef) + { + Decl* targetTypeDecl = nullptr; + if (newParentDeclRef.getDecl()->memberDictionary.TryGetValue(this->GetDeclRef().decl->getName(), targetTypeDecl)) + { + if (auto typeDefDecl = targetTypeDecl->As()) + return GetType(DeclRef(typeDefDecl, subst)); + else + return DeclRefType::Create(this->getSession(), DeclRef(targetTypeDecl, subst)); + } } } + return this; } @@ -981,6 +1026,69 @@ void Type::accept(IValVisitor* visitor, void* extra) return this; } + // GenericConstraintDeclRefType + + String GenericConstraintDeclRefType::ToString() + { + // TODO: what is appropriate here? + return ""; + } + + bool GenericConstraintDeclRefType::EqualsImpl(Type * type) + { + if (auto other = type->As()) + { + return supType->Equals(other->supType) && subType->Equals(other->subType); + } + return false; + } + + RefPtr GenericConstraintDeclRefType::SubstituteImpl(Substitutions* subst, int* ioDiff) + { + auto genParamDecl = subType.As()->declRef.As(); + // search for a substitution that might apply to us + for (auto s = subst; s; s = s->outer.Ptr()) + { + // the generic decl associated with the substitution list must be + // the generic decl that declared this parameter + auto genericDecl = s->genericDecl; + if (genericDecl != genParamDecl.getDecl()->ParentDecl) + continue; + int index = 0; + for (auto m : genericDecl->Members) + { + if (m.Ptr() == genParamDecl.getDecl()) + { + // We've found it, so return the corresponding specialization argument + (*ioDiff)++; + return s->args[index]; + } + else if (auto typeParam = m.As()) + { + index++; + } + else if (auto valParam = m.As()) + { + index++; + } + else + { + } + } + } + return this; + } + + int GenericConstraintDeclRefType::GetHashCode() + { + return combineHash(subType.GetHashCode(), supType.GetHashCode()); + } + + Type* GenericConstraintDeclRefType::CreateCanonicalType() + { + return this; + } + // ArithmeticExpressionType // VectorExpressionType diff --git a/source/slang/type-defs.h b/source/slang/type-defs.h index 15dfe3e07..2052e1eb8 100644 --- a/source/slang/type-defs.h +++ b/source/slang/type-defs.h @@ -449,7 +449,6 @@ SYNTAX_CLASS(FuncType, Type) FIELD(List>, paramTypes) FIELD(RefPtr, resultType) - RAW( FuncType() {} @@ -495,7 +494,7 @@ END_SYNTAX_CLASS() // The "type" of an expression that references a asscoiated type decl (via 'assoctype' keyword). SYNTAX_CLASS(AssocTypeDeclRefType, Type) DECL_FIELD(DeclRef, declRef) - + DECL_FIELD(RefPtr, sourceType) RAW( AssocTypeDeclRefType() {} @@ -515,4 +514,34 @@ SYNTAX_CLASS(AssocTypeDeclRefType, Type) virtual int GetHashCode() override; virtual Type* CreateCanonicalType() override; ) +END_SYNTAX_CLASS() + +// The "type" of an generic constraint, which wraps both the sub and sup (interface) type +// the sub type can be used in associated type substitution in later type evaluation +SYNTAX_CLASS(GenericConstraintDeclRefType, Type) + DECL_FIELD(RefPtr, subType) + DECL_FIELD(RefPtr, supType) +RAW( + GenericConstraintDeclRefType() + {} + GenericConstraintDeclRefType(Session* session, + RefPtr sub, + RefPtr sup) + : subType(sub), supType(sup) + { + setSession(session); + } + + + RefPtr const& GetSupType() const { return supType; } + RefPtr const& GetSubType() const { return subType; } + + virtual String ToString() override; + + protected: + virtual RefPtr SubstituteImpl(Substitutions* subst, int* ioDiff) override; + virtual bool EqualsImpl(Type * type) override; + virtual int GetHashCode() override; + virtual Type* CreateCanonicalType() override; +) END_SYNTAX_CLASS() \ No newline at end of file diff --git a/tests/compute/assoctype-complex.slang b/tests/compute/assoctype-complex.slang new file mode 100644 index 000000000..3e590b2e0 --- /dev/null +++ b/tests/compute/assoctype-complex.slang @@ -0,0 +1,44 @@ +RWStructuredBuffer outputBuffer; +interface IBase +{ + associatedtype V; + V sub(V a0, V a1); +} +interface ISimple +{ + associatedtype U : IBase; + U.V add(U v0, U v1); +} + +struct Val : IBase +{ + typedef int V; + V sub(V a0, V a1) + { + return a0-a1; + } +}; + +struct Simple : ISimple +{ + typedef Val U; + Val.V add(U v0, U v1) + { + return v0.sub(4, v1.sub(1,2)); + } +}; + +__generic +T.U.V test(T simple, T.U v0, T.U v1) +{ + return simple.add(v0, v1); +} + +[numthreads(4, 1, 1)] +void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID) +{ + Simple s; + Val v0, v1; + float outVal = test(s, v0, v1); // == 1.0 + outputBuffer[0] = outVal; +} \ No newline at end of file diff --git a/tests/compute/assoctype-simple.slang b/tests/compute/assoctype-simple.slang index e03bb4e54..0f160c9c0 100644 --- a/tests/compute/assoctype-simple.slang +++ b/tests/compute/assoctype-simple.slang @@ -31,5 +31,5 @@ void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID) { Simple s; float outVal = test(s, 2.0, 1.0); // == 3.0 - outputBuffer[tid] = outVal; + outputBuffer[dispatchThreadID.x] = outVal; } \ No newline at end of file diff --git a/tests/compute/assoctype-simple.slang.expected.txt b/tests/compute/assoctype-simple.slang.expected.txt new file mode 100644 index 000000000..e54af3bc8 --- /dev/null +++ b/tests/compute/assoctype-simple.slang.expected.txt @@ -0,0 +1,4 @@ +40400000 +40400000 +40400000 +40400000 diff --git a/tools/render-test/render-d3d11.cpp b/tools/render-test/render-d3d11.cpp index ee34445d0..4b61b57c3 100644 --- a/tools/render-test/render-d3d11.cpp +++ b/tools/render-test/render-d3d11.cpp @@ -714,7 +714,8 @@ public: if (request.computeShader.name) { auto dxComputeShaderBlob = compileHLSLShader(request.computeShader.source.path, request.computeShader.source.text, request.computeShader.name, request.computeShader.profile); - if (!dxComputeShaderBlob) return nullptr; + if (!dxComputeShaderBlob) + return nullptr; ID3D11ComputeShader* dxComputeShader; -- cgit v1.2.3 From d5e2319c33115d0241dd9d2047c0a5f029553dde Mon Sep 17 00:00:00 2001 From: "YONGH\\yongh" Date: Thu, 2 Nov 2017 19:21:15 -0400 Subject: work inprogress --- source/slang/check.cpp | 53 +++++++++++++++--------- source/slang/lookup.cpp | 21 ++++++++++ source/slang/parser.cpp | 25 +++++++++++- source/slang/syntax.cpp | 36 ++-------------- tests/compute/assoctype-complex.slang | 59 +++++++++++++++++++++++++++ tests/compute/assoctype-complex.slang._ignore | 44 -------------------- tests/compute/generics-constraint1.slang | 17 ++++++++ 7 files changed, 157 insertions(+), 98 deletions(-) create mode 100644 tests/compute/assoctype-complex.slang delete mode 100644 tests/compute/assoctype-complex.slang._ignore create mode 100644 tests/compute/generics-constraint1.slang (limited to 'source/slang/check.cpp') diff --git a/source/slang/check.cpp b/source/slang/check.cpp index 2f4ed2ce8..dc4e48545 100644 --- a/source/slang/check.cpp +++ b/source/slang/check.cpp @@ -169,23 +169,18 @@ namespace Slang sexpr->declRef = declRef; expr = sexpr; } - if (auto assocTypeDeclRef = declRef.As()) + if (auto constraintType = expr->type->As()) { - if (auto genConstraintType = baseExpr->type->As()) - { - // if this is a reference from a generic parameter, we need to generate a AssocTypeDeclRefType type. - // for example, if we have an expression T.U where T:ISimple, and U is an associated type defined in ISimple. - // then this expression should evaluate to AssocTypeDeclRefType(T, U). - auto assocTypeDeclType = new AssocTypeDeclRefType(); - assocTypeDeclType->declRef = assocTypeDeclRef; - assocTypeDeclType->sourceType = genConstraintType->subType; - assocTypeDeclType->setSession(getSession()); - expr->type = QualType(getTypeType(assocTypeDeclType)); - } + if (baseExpr->type->As()) + constraintType->subType = baseExpr->type->As()->type; + else + constraintType->subType = baseExpr->type; + } - else if (auto funcDeclRef = declRef.As()) + + if (auto genConstraintType = baseExpr->type->As()) { - if (auto genConstraintType = baseExpr->type->As()) + if (auto funcDeclRef = declRef.As()) { // if this is call expression, propagate the source associated type to the result type auto funcType = expr->type->As(); @@ -201,9 +196,24 @@ namespace Slang newFuncType->setSession(funcType->getSession()); expr->type = QualType(newFuncType); } - + } + else if (auto assocTypeDeclRef = declRef.As()) + { + auto assocTypeDeclType = new AssocTypeDeclRefType(); + assocTypeDeclType->declRef = assocTypeDeclRef; + assocTypeDeclType->sourceType = genConstraintType->subType; + assocTypeDeclType->setSession(getSession()); + expr->type = QualType(getTypeType(assocTypeDeclType)); } } + else if (auto assocTypeDeclRef = declRef.As()) + { + auto assocTypeDeclType = new AssocTypeDeclRefType(); + assocTypeDeclType->declRef = assocTypeDeclRef; + assocTypeDeclType->sourceType = baseExpr->type; + assocTypeDeclType->setSession(getSession()); + expr->type = QualType(getTypeType(assocTypeDeclType)); + } return expr; } else @@ -1262,6 +1272,14 @@ namespace Slang checkDecl(genericDecl->inner); } + void visitGenericTypeConstraintDecl(GenericTypeConstraintDecl * genericConstraintDecl) + { + // check the type being inherited from + auto base = genericConstraintDecl->sup; + base = TranslateTypeNode(base); + genericConstraintDecl->sup = base; + } + void visitInheritanceDecl(InheritanceDecl* inheritanceDecl) { // check the type being inherited from @@ -1325,11 +1343,6 @@ namespace Slang // These are only used in the stdlib, so no checking is needed for now } - void visitGenericTypeConstraintDecl(GenericTypeConstraintDecl*) - { - // These are only used in the stdlib, so no checking is needed for now - } - void visitModifier(Modifier*) { // Do nothing with modifiers for now diff --git a/source/slang/lookup.cpp b/source/slang/lookup.cpp index c0cb657c4..b97dac560 100644 --- a/source/slang/lookup.cpp +++ b/source/slang/lookup.cpp @@ -453,6 +453,27 @@ void lookUpMemberImpl( } } } + else if (auto assocTypeDeclRefType = type->As()) + { + auto assocTypeDeclRef = assocTypeDeclRefType->declRef; + for (auto constraintDeclRef : getMembersOfType(assocTypeDeclRef)) + { + // The super-type in the constraint (e.g., `Foo` in `T : Foo`) + // will tell us a type we should use for lookup. + auto bound = GetSup(constraintDeclRef); + + // Go ahead and use the target type, with an appropriate breadcrumb + // to indicate that we indirected through a type constraint. + + BreadcrumbInfo breadcrumb; + breadcrumb.prev = inBreadcrumbs; + breadcrumb.kind = LookupResultItem::Breadcrumb::Kind::Constraint; + breadcrumb.declRef = constraintDeclRef; + + // TODO: Need to consider case where this might recurse infinitely. + lookUpMemberImpl(session, semantics, name, bound, ioResult, &breadcrumb); + } + } } LookupResult lookUpMember( diff --git a/source/slang/parser.cpp b/source/slang/parser.cpp index 224450a66..bf85356db 100644 --- a/source/slang/parser.cpp +++ b/source/slang/parser.cpp @@ -2113,7 +2113,30 @@ namespace Slang auto nameToken = parser->ReadToken(TokenType::Identifier); assocTypeDecl->nameAndLoc = NameLoc(nameToken); assocTypeDecl->loc = nameToken.loc; - parseOptionalInheritanceClause(parser, assocTypeDecl.Ptr()); + if (AdvanceIf(parser, TokenType::Colon)) + { + while (!parser->tokenReader.IsAtEnd()) + { + auto paramConstraint = new GenericTypeConstraintDecl(); + parser->FillPosition(paramConstraint); + + auto paramType = DeclRefType::Create( + parser->getSession(), + DeclRef(assocTypeDecl, nullptr)); + + auto paramTypeExpr = new SharedTypeExpr(); + paramTypeExpr->loc = assocTypeDecl->loc; + paramTypeExpr->base.type = paramType; + paramTypeExpr->type = QualType(getTypeType(paramType)); + + paramConstraint->sub = TypeExp(paramTypeExpr); + paramConstraint->sup = parser->ParseTypeExp(); + + AddMember(assocTypeDecl, paramConstraint); + if (!AdvanceIf(parser, TokenType::Comma)) + break; + } + } parser->ReadToken(TokenType::Semicolon); return assocTypeDecl; } diff --git a/source/slang/syntax.cpp b/source/slang/syntax.cpp index fd7fc0e14..3e38955ba 100644 --- a/source/slang/syntax.cpp +++ b/source/slang/syntax.cpp @@ -961,7 +961,8 @@ void Type::accept(IValVisitor* visitor, void* extra) { if (!sourceType) return this; - if (auto parentDeclRefType = sourceType->As()) + auto substSourceType = sourceType->SubstituteImpl(subst, ioDiff); + if (auto parentDeclRefType = substSourceType.As()) { auto parentDeclRef = parentDeclRefType->declRef; DeclRef newParentDeclRef = parentDeclRef.As(); @@ -1045,38 +1046,7 @@ void Type::accept(IValVisitor* visitor, void* extra) RefPtr GenericConstraintDeclRefType::SubstituteImpl(Substitutions* subst, int* ioDiff) { - auto genParamDecl = subType.As()->declRef.As(); - // search for a substitution that might apply to us - for (auto s = subst; s; s = s->outer.Ptr()) - { - // the generic decl associated with the substitution list must be - // the generic decl that declared this parameter - auto genericDecl = s->genericDecl; - if (genericDecl != genParamDecl.getDecl()->ParentDecl) - continue; - int index = 0; - for (auto m : genericDecl->Members) - { - if (m.Ptr() == genParamDecl.getDecl()) - { - // We've found it, so return the corresponding specialization argument - (*ioDiff)++; - return s->args[index]; - } - else if (auto typeParam = m.As()) - { - index++; - } - else if (auto valParam = m.As()) - { - index++; - } - else - { - } - } - } - return this; + return subType->SubstituteImpl(subst, ioDiff); } int GenericConstraintDeclRefType::GetHashCode() diff --git a/tests/compute/assoctype-complex.slang b/tests/compute/assoctype-complex.slang new file mode 100644 index 000000000..de3f1a103 --- /dev/null +++ b/tests/compute/assoctype-complex.slang @@ -0,0 +1,59 @@ +//TEST(smoke, compute):COMPARE_COMPUTE:-xslang -use-ir +//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out + +RWStructuredBuffer outputBuffer; +interface IBase +{ + associatedtype V; + V sub(V a0, V a1); +} +interface ISimple +{ + associatedtype U : IBase; + U.V add(U v0, U v1); +} + +struct Val : IBase +{ + typedef int V; + V sub(V a0, V a1) + { + return a0-a1; + } +}; + +struct Simple : ISimple +{ + typedef Val U; + Val.V add(U v0, U v1) + { + return v0.sub(4, v1.sub(1,2)); + } +}; +/* +__generic +T.U.V test(T simple, T.U v0, T.U v1) +{ + return simple.add(v0, v1); +} + +__generic +T test(T v0, T v1) +{ + return v0 + v1; +} +*/ +__generic +T test(T v0, T v1) +{ + return T(3.0); +} +[numthreads(4, 1, 1)] +void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID) +{ + //Simple s; + //Val v0, v1; + //float outVal = test(s, v0, v1); // == 1.0 + float outVal = test(1.0, 2.0); + outputBuffer[dispatchThreadID.x] = outVal; +} \ No newline at end of file diff --git a/tests/compute/assoctype-complex.slang._ignore b/tests/compute/assoctype-complex.slang._ignore deleted file mode 100644 index 3e590b2e0..000000000 --- a/tests/compute/assoctype-complex.slang._ignore +++ /dev/null @@ -1,44 +0,0 @@ -RWStructuredBuffer outputBuffer; -interface IBase -{ - associatedtype V; - V sub(V a0, V a1); -} -interface ISimple -{ - associatedtype U : IBase; - U.V add(U v0, U v1); -} - -struct Val : IBase -{ - typedef int V; - V sub(V a0, V a1) - { - return a0-a1; - } -}; - -struct Simple : ISimple -{ - typedef Val U; - Val.V add(U v0, U v1) - { - return v0.sub(4, v1.sub(1,2)); - } -}; - -__generic -T.U.V test(T simple, T.U v0, T.U v1) -{ - return simple.add(v0, v1); -} - -[numthreads(4, 1, 1)] -void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID) -{ - Simple s; - Val v0, v1; - float outVal = test(s, v0, v1); // == 1.0 - outputBuffer[0] = outVal; -} \ No newline at end of file diff --git a/tests/compute/generics-constraint1.slang b/tests/compute/generics-constraint1.slang new file mode 100644 index 000000000..ff90c1cc9 --- /dev/null +++ b/tests/compute/generics-constraint1.slang @@ -0,0 +1,17 @@ +//TEST(smoke, compute):COMPARE_COMPUTE:-xslang -use-ir +//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out + +RWStructuredBuffer outputBuffer; + +__generic +T test(T v0, T v1) +{ + return T(3.0); +} + +[numthreads(4, 1, 1)] +void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID) +{ + float outVal = test(1.0, 2.0); + outputBuffer[dispatchThreadID.x] = outVal; +} \ No newline at end of file -- cgit v1.2.3 From a0458266d7cd5d802b8c51e6a997b4bf0d9beb82 Mon Sep 17 00:00:00 2001 From: Yong He Date: Fri, 3 Nov 2017 09:38:02 -0400 Subject: in-progress work --- source/core/core.natvis | 2 +- source/slang/bytecode.cpp | 56 +++-- source/slang/bytecode.h | 2 +- source/slang/check.cpp | 118 ++++------- source/slang/decl-defs.h | 2 +- source/slang/emit.cpp | 11 +- source/slang/ir.cpp | 97 +++++---- source/slang/lookup.cpp | 32 +-- source/slang/lower-to-ir.cpp | 40 ++-- source/slang/lower.cpp | 43 ++-- source/slang/mangle.cpp | 6 +- source/slang/slang.natvis | 27 ++- source/slang/syntax-base-defs.h | 54 ++++- source/slang/syntax.cpp | 340 +++++++++++++------------------ source/slang/type-defs.h | 55 ----- source/slang/vm.cpp | 32 ++- tests/compute/assoctype-complex.slang | 20 +- tests/compute/generics-constraint1.slang | 2 +- tests/compute/generics-constructor.slang | 17 ++ 19 files changed, 434 insertions(+), 522 deletions(-) create mode 100644 tests/compute/generics-constructor.slang (limited to 'source/slang/check.cpp') diff --git a/source/core/core.natvis b/source/core/core.natvis index 3d9ac702e..91fdbb49b 100644 --- a/source/core/core.natvis +++ b/source/core/core.natvis @@ -54,7 +54,7 @@ - + pointer empty RefPtr {*pointer} diff --git a/source/slang/bytecode.cpp b/source/slang/bytecode.cpp index f1b23849d..ee055a01f 100644 --- a/source/slang/bytecode.cpp +++ b/source/slang/bytecode.cpp @@ -77,7 +77,6 @@ struct BytecodeGenerationPtr BytecodeGenerationPtr operator+(Int index) const { - UInt size = sizeof(T); Int delta = index * sizeof(T); UInt newOffset = offset + delta; return BytecodeGenerationPtr( @@ -157,7 +156,7 @@ BCPtr::RawVal allocateRaw( for(size_t ii = currentOffset; ii < endOffset; ++ii) context->shared->bytecode.Add(0); - return beginOffset; + return (BCPtr::RawVal)beginOffset; } template @@ -196,7 +195,7 @@ void encodeUInt( { if( value < 128 ) { - encodeUInt8(context, value); + encodeUInt8(context, (uint8_t)value); return; } @@ -256,9 +255,8 @@ BCConst getGlobalValue( UInt constID = context->shared->constants.Count(); context->shared->constants.Add(value); - BCConst bcConst; bcConst.flavor = kBCConstFlavor_Constant; - bcConst.id = constID; + bcConst.id = (uint32_t)constID; context->shared->mapValueToGlobal.Add(value, bcConst); @@ -270,10 +268,10 @@ BCConst getGlobalValue( break; } + bcConst.flavor = (uint32_t) -1; + bcConst.id = (uint32_t)-9999; SLANG_UNEXPECTED("no ID for inst"); - bcConst.flavor = (BCConstFlavor) -1; - bcConst.id = -9999; - return bcConst; + //return bcConst; } Int getLocalID( @@ -348,7 +346,6 @@ void generateBytecodeForInst( // auto argCount = inst->getArgCount(); - auto type = inst->getType(); encodeUInt(context, inst->op); encodeOperand(context, inst->getType()); encodeUInt(context, argCount); @@ -400,9 +397,9 @@ void generateBytecodeForInst( unsigned char buffer[size]; memcpy(buffer, &ii->u.floatVal, sizeof(buffer)); - for(UInt ii = 0; ii < size; ++ii) + for(UInt i = 0; i < size; ++i) { - encodeUInt8(context, buffer[ii]); + encodeUInt8(context, buffer[i]); } // destination: @@ -479,7 +476,7 @@ BytecodeGenerationPtr emitBCType( auto bcArgs = (bcType + 1).bitCast>(); bcType->op = op; - bcType->argCount = argCount; + bcType->argCount = (uint32_t)argCount; for(UInt aa = 0; aa < argCount; ++aa) { @@ -489,7 +486,7 @@ BytecodeGenerationPtr emitBCType( UInt id = context->shared->bcTypes.Count(); context->shared->mapTypeToID.Add(type, id); context->shared->bcTypes.Add(bcType); - bcType->id = id; + bcType->id = (uint32_t)id; return bcType; } @@ -577,7 +574,6 @@ BytecodeGenerationPtr emitBCTypeImpl( SLANG_UNEXPECTED("unimplemented"); - return BytecodeGenerationPtr(); } BytecodeGenerationPtr emitBCType( @@ -703,7 +699,7 @@ BytecodeGenerationPtr generateBytecodeSymbolForInst( // Allocate the array of block objects to be stored in the // bytecode file. auto bcBlocks = allocateArray(context, blockCount); - bcFunc->blockCount = blockCount; + bcFunc->blockCount = (uint32_t)blockCount; bcFunc->blocks = bcBlocks; // Now loop through the blocks again, and allocate the storage @@ -750,7 +746,7 @@ BytecodeGenerationPtr generateBytecodeSymbolForInst( } } - bcBlocks[blockID].paramCount = paramCount; + bcBlocks[blockID].paramCount = (uint32_t)paramCount; } // Okay, we've counted how many registers we need for each block, @@ -758,7 +754,7 @@ BytecodeGenerationPtr generateBytecodeSymbolForInst( UInt regCount = regCounter; auto bcRegs = allocateArray(context, regCount); - bcFunc->regCount = regCount; + bcFunc->regCount = (uint32_t)regCount; bcFunc->regs = bcRegs; // Now we will loop over things again to fill in the information @@ -786,7 +782,7 @@ BytecodeGenerationPtr generateBytecodeSymbolForInst( #if 0 bcRegs[localID].name = tryGenerateNameForSymbol(context, pp); #endif - bcRegs[localID].previousVarIndexPlusOne = localID; + bcRegs[localID].previousVarIndexPlusOne = (uint32_t)localID; bcRegs[localID].typeID = getTypeIDForGlobalSymbol(context, pp); } @@ -808,7 +804,7 @@ BytecodeGenerationPtr generateBytecodeSymbolForInst( #if 0 bcRegs[localID].name = tryGenerateNameForSymbol(context, ii); #endif - bcRegs[localID].previousVarIndexPlusOne = localID; + bcRegs[localID].previousVarIndexPlusOne = (uint32_t)localID; bcRegs[localID].typeID = getTypeIDForGlobalSymbol(context, ii); } break; @@ -828,11 +824,11 @@ BytecodeGenerationPtr generateBytecodeSymbolForInst( #if 0 bcRegs[localID].name = tryGenerateNameForSymbol(context, ii); #endif - bcRegs[localID].previousVarIndexPlusOne = localID; + bcRegs[localID].previousVarIndexPlusOne = (uint32_t)localID; bcRegs[localID].typeID = getTypeIDForGlobalSymbol(context, ii); bcRegs[localID+1].op = ii->op; - bcRegs[localID+1].previousVarIndexPlusOne = localID+1; + bcRegs[localID+1].previousVarIndexPlusOne = (uint32_t)localID+1; bcRegs[localID+1].typeID = getTypeID(context, (ii->getType()->As())->getValueType()); } @@ -840,7 +836,7 @@ BytecodeGenerationPtr generateBytecodeSymbolForInst( } } } - assert(regCounter == regCount); + assert((UInt)regCounter == regCount); // Now that we've allocated our blocks and our registers // we can go through the actual process of emitting instructions. Hooray! @@ -851,7 +847,7 @@ BytecodeGenerationPtr generateBytecodeSymbolForInst( List blockOffsets; for( auto bb = irFunc->getFirstBlock(); bb; bb = bb->getNextBlock() ) { - UInt blockID = blockCounter++; + blockCounter++; // Get local bytecode offset for current block. UInt blockOffset = subContext->currentBytecode.Count(); @@ -903,7 +899,7 @@ BytecodeGenerationPtr generateBytecodeSymbolForInst( UInt constCount = subContext->remappedGlobalSymbols.Count(); auto bcConsts = allocateArray(context, constCount); - bcFunc->constCount = constCount; + bcFunc->constCount = (uint32_t)constCount; bcFunc->consts = bcConsts; for( UInt cc = 0; cc < constCount; ++cc ) @@ -969,7 +965,7 @@ BytecodeGenerationPtr generateBytecodeForModule( // Ensure that local code inside functions can see these symbols BCConst bcConst; bcConst.flavor = kBCConstFlavor_GlobalSymbol; - bcConst.id = globalID; + bcConst.id = (uint32_t)globalID; context->shared->mapValueToGlobal.Add(gv, bcConst); // In the global scope, global IDs are also the local IDs @@ -978,7 +974,7 @@ BytecodeGenerationPtr generateBytecodeForModule( auto bcSymbols = allocateArray>(context, symbolCount); - bcModule->symbolCount = symbolCount; + bcModule->symbolCount = (uint32_t)symbolCount; bcModule->symbols = bcSymbols; for( auto gv = irModule->getFirstGlobalValue(); gv; gv = gv->getNextValue() ) @@ -998,7 +994,7 @@ BytecodeGenerationPtr generateBytecodeForModule( // At this point we should have identified all the literals we need: UInt constantCount = context->shared->constants.Count(); auto bcConstants = allocateArray(context, constantCount); - bcModule->constantCount = constantCount; + bcModule->constantCount = (uint32_t)constantCount; bcModule->constants = bcConstants; for(UInt cc = 0; cc < constantCount; ++cc) @@ -1026,7 +1022,7 @@ BytecodeGenerationPtr generateBytecodeForModule( // At this point we should have collected all the types we need: UInt typeCount = context->shared->bcTypes.Count(); auto bcTypes = allocateArray>(context, typeCount); - bcModule->typeCount = typeCount; + bcModule->typeCount = (uint32_t)typeCount; bcModule->types = bcTypes; for(UInt tt = 0; tt < typeCount; ++tt) @@ -1055,8 +1051,6 @@ void generateBytecodeContainer( // TODO: Need to dump BC representation of compiled kernel codes // for each specified code-generation target. - UInt translationUnitCount = compileReq->translationUnits.Count(); - List> bcModulesList; for (auto translationUnitReq : compileReq->translationUnits) { @@ -1065,7 +1059,7 @@ void generateBytecodeContainer( } UInt bcModuleCount = bcModulesList.Count(); - header->moduleCount = bcModuleCount; + header->moduleCount = (uint32_t)bcModuleCount; auto bcModules = allocateArray>(context, bcModuleCount); header->modules = bcModules; diff --git a/source/slang/bytecode.h b/source/slang/bytecode.h index 75b9f15cd..f1ad52c32 100644 --- a/source/slang/bytecode.h +++ b/source/slang/bytecode.h @@ -56,7 +56,7 @@ struct BCPtr { if (ptr) { - rawVal = (char*)ptr - (char*)this; + rawVal = (RawVal)((char*)ptr - (char*)this); } else { diff --git a/source/slang/check.cpp b/source/slang/check.cpp index dc4e48545..137b1c451 100644 --- a/source/slang/check.cpp +++ b/source/slang/check.cpp @@ -148,15 +148,13 @@ namespace Slang if (baseExpr) { RefPtr expr; - + if (baseExpr->type->As()) { auto sexpr = new StaticMemberExpr(); sexpr->loc = loc; sexpr->BaseExpression = baseExpr; sexpr->name = declRef.GetName(); - sexpr->type = GetTypeForDeclRef(declRef); - sexpr->declRef = declRef; expr = sexpr; } else @@ -165,54 +163,24 @@ namespace Slang sexpr->loc = loc; sexpr->BaseExpression = baseExpr; sexpr->name = declRef.GetName(); - sexpr->type = GetTypeForDeclRef(declRef); sexpr->declRef = declRef; expr = sexpr; } - if (auto constraintType = expr->type->As()) + if (auto assocTypeDecl = declRef.As()) { - if (baseExpr->type->As()) - constraintType->subType = baseExpr->type->As()->type; - else - constraintType->subType = baseExpr->type; - + RefPtr subst = new ThisTypeSubstitution(); + subst->sourceType = baseExpr->type.type; + if (auto typeType = subst->sourceType.As()) + subst->sourceType = typeType->type; + expr->type = GetTypeForDeclRef(DeclRef(assocTypeDecl.getDecl(), subst)); } - - if (auto genConstraintType = baseExpr->type->As()) + else if (auto constraintDecl = declRef.As()) { - if (auto funcDeclRef = declRef.As()) - { - // if this is call expression, propagate the source associated type to the result type - auto funcType = expr->type->As(); - if (auto assocRsType = funcType->resultType.As()) - { - RefPtr newFuncType = new FuncType(); - newFuncType->paramTypes = funcType->paramTypes; - RefPtr newRsType = new AssocTypeDeclRefType(); - newRsType->declRef = assocRsType->declRef; - newRsType->sourceType = genConstraintType->subType; - newRsType->setSession(getSession()); - newFuncType->resultType = newRsType; - newFuncType->setSession(funcType->getSession()); - expr->type = QualType(newFuncType); - } - } - else if (auto assocTypeDeclRef = declRef.As()) - { - auto assocTypeDeclType = new AssocTypeDeclRefType(); - assocTypeDeclType->declRef = assocTypeDeclRef; - assocTypeDeclType->sourceType = genConstraintType->subType; - assocTypeDeclType->setSession(getSession()); - expr->type = QualType(getTypeType(assocTypeDeclType)); - } + expr->type = baseExpr->type; } - else if (auto assocTypeDeclRef = declRef.As()) + else { - auto assocTypeDeclType = new AssocTypeDeclRefType(); - assocTypeDeclType->declRef = assocTypeDeclRef; - assocTypeDeclType->sourceType = baseExpr->type; - assocTypeDeclType->setSession(getSession()); - expr->type = QualType(getTypeType(assocTypeDeclType)); + expr->type = GetTypeForDeclRef(declRef); } return expr; } @@ -449,7 +417,7 @@ namespace Slang DeclRef genericDeclRef, List> const& args) { - RefPtr subst = new Substitutions(); + RefPtr subst = new GenericSubstitution(); subst->genericDecl = genericDeclRef.getDecl(); subst->outer = genericDeclRef.substitutions; @@ -2097,10 +2065,10 @@ namespace Slang return true; } - RefPtr createDummySubstitutions( + RefPtr createDummySubstitutions( GenericDecl* genericDecl) { - RefPtr subst = new Substitutions(); + RefPtr subst = new GenericSubstitution(); subst->genericDecl = genericDecl; for (auto dd : genericDecl->Members) { @@ -3115,7 +3083,7 @@ namespace Slang session, "Vector").As(); auto vectorTypeDecl = vectorGenericDecl->inner; - auto substitutions = new Substitutions(); + auto substitutions = new GenericSubstitution(); substitutions->genericDecl = vectorGenericDecl.Ptr(); substitutions->args.Add(elementType); substitutions->args.Add(elementCount); @@ -3447,7 +3415,7 @@ namespace Slang // to `interfaceDeclRef`. // SLANG_UNEXPECTED("reflexive type witness"); - return nullptr; + //return nullptr; } auto breadcrumbs = inBreadcrumbs; @@ -3462,7 +3430,7 @@ namespace Slang // because `A : B` and `B : C` then `A : C` // SLANG_UNEXPECTED("transitive type witness"); - return nullptr; + //return nullptr; } // Simple case: we have a single declaration @@ -3815,7 +3783,7 @@ namespace Slang // Consruct a reference to the extension with our constraint variables // as the - RefPtr solvedSubst = new Substitutions(); + RefPtr solvedSubst = new GenericSubstitution(); solvedSubst->genericDecl = genericDeclRef.getDecl(); solvedSubst->outer = genericDeclRef.substitutions; solvedSubst->args = args; @@ -4084,8 +4052,9 @@ namespace Slang // We will go ahead and hang onto the arguments that we've // already checked, since downstream validation might need // them. - candidate.subst = new Substitutions(); - auto& checkedArgs = candidate.subst->args; + auto genSubst = new GenericSubstitution(); + candidate.subst = genSubst; + auto& checkedArgs = genSubst->args; int aa = 0; for (auto memberRef : getMembers(genericDeclRef)) @@ -4202,7 +4171,7 @@ namespace Slang // Create a witness that attests to the fact that `type` // is equal to itself. RefPtr createTypeEqualityWitness( - Type* type) + Type* /*type*/) { SLANG_UNEXPECTED("unimplemented"); } @@ -4258,7 +4227,7 @@ namespace Slang // We should have the existing arguments to the generic // handy, so that we can construct a substitution list. - RefPtr subst = candidate.subst; + RefPtr subst = candidate.subst.As(); assert(subst); subst->genericDecl = genericDeclRef.getDecl(); @@ -4325,7 +4294,7 @@ namespace Slang RefPtr createGenericDeclRef( RefPtr baseExpr, RefPtr originalExpr, - RefPtr subst) + RefPtr subst) { auto baseDeclRefExpr = baseExpr.As(); if (!baseDeclRefExpr) @@ -4437,7 +4406,7 @@ namespace Slang return createGenericDeclRef( baseExpr, context.originalExpr, - candidate.subst); + candidate.subst.As()); break; default: @@ -4734,22 +4703,23 @@ namespace Slang // They must both be NULL or non-NULL if (!fst || !snd) return fst == snd; - + auto fstGen = fst.As(); + auto sndGen = snd.As(); // They must be specializing the same generic - if (fst->genericDecl != snd->genericDecl) + if (fstGen->genericDecl != sndGen->genericDecl) return false; // Their arguments must unify - SLANG_RELEASE_ASSERT(fst->args.Count() == snd->args.Count()); - UInt argCount = fst->args.Count(); + SLANG_RELEASE_ASSERT(fstGen->args.Count() == sndGen->args.Count()); + UInt argCount = fstGen->args.Count(); for (UInt aa = 0; aa < argCount; ++aa) { - if (!TryUnifyVals(constraints, fst->args[aa], snd->args[aa])) + if (!TryUnifyVals(constraints, fstGen->args[aa], sndGen->args[aa])) return false; } // Their "base" specializations must unify - if (!TryUnifySubstitutions(constraints, fst->outer, snd->outer)) + if (!TryUnifySubstitutions(constraints, fstGen->outer, sndGen->outer)) return false; return true; @@ -5304,11 +5274,12 @@ namespace Slang if( parentGenericDeclRef ) { SLANG_RELEASE_ASSERT(declRef.substitutions); - SLANG_RELEASE_ASSERT(declRef.substitutions->genericDecl == parentGenericDeclRef.getDecl()); + auto genSubst = declRef.substitutions.As(); + SLANG_RELEASE_ASSERT(genSubst->genericDecl == parentGenericDeclRef.getDecl()); sb << "<"; bool first = true; - for(auto arg : declRef.substitutions->args) + for(auto arg : genSubst->args) { if(!first) sb << ", "; formatVal(sb, arg); @@ -6069,7 +6040,7 @@ namespace Slang RefPtr visitStaticMemberExpr(StaticMemberExpr* expr) { SLANG_UNEXPECTED("should not occur in unchecked AST"); - return expr; + //return expr; } RefPtr lookupResultFailure( @@ -6495,26 +6466,11 @@ namespace Slang *outTypeResult = type; return QualType(getTypeType(type)); } - else if (auto constraintDeclRef = declRef.As()) - { - // When we access a constraint or an inheritance decl (as a member), - // we are conceptually performing a "cast" to the given super-type, - // with the declaration showing that such a cast is legal. - auto type = new GenericConstraintDeclRefType(session, GetSub(constraintDeclRef), GetSup(constraintDeclRef)); - return QualType(type); - } else if (auto funcDeclRef = declRef.As()) { auto type = getFuncType(session, funcDeclRef); return QualType(type); } - else if (auto assocTypeDeclRef = declRef.As()) - { - auto type = new AssocTypeDeclRefType(assocTypeDeclRef); - type->setSession(session); - *outTypeResult = type; - return QualType(getTypeType(type)); - } if( sink ) { sink->diagnose(declRef, Diagnostics::unimplemented, "cannot form reference to this kind of declaration"); @@ -6558,7 +6514,7 @@ namespace Slang if(decl != genericDecl->inner) return parentSubst; - RefPtr subst = new Substitutions(); + RefPtr subst = new GenericSubstitution(); subst->genericDecl = genericDecl; subst->outer = parentSubst; diff --git a/source/slang/decl-defs.h b/source/slang/decl-defs.h index bb8c26f58..9c010d156 100644 --- a/source/slang/decl-defs.h +++ b/source/slang/decl-defs.h @@ -123,7 +123,7 @@ SYNTAX_CLASS(TypeDefDecl, SimpleTypeDecl) END_SYNTAX_CLASS() // An 'assoctype' declaration, it is a container of inheritance clauses -SYNTAX_CLASS(AssocTypeDecl, ContainerDecl) +SYNTAX_CLASS(AssocTypeDecl, AggTypeDecl) END_SYNTAX_CLASS() // A scope for local declarations (e.g., as part of a statement) diff --git a/source/slang/emit.cpp b/source/slang/emit.cpp index 9caad2e1a..2627e1f37 100644 --- a/source/slang/emit.cpp +++ b/source/slang/emit.cpp @@ -1052,15 +1052,6 @@ struct EmitVisitor EmitDeclarator(arg.declarator); } - void visitAssocTypeDeclRefType(AssocTypeDeclRefType* /*type*/, TypeEmitArg const& /*arg*/) - { - //SLANG_UNREACHABLE("visitAssocTypeDeclRefType in EmitVisitor"); - } - void visitGenericConstraintDeclRefType(GenericConstraintDeclRefType* /*type*/, TypeEmitArg const& /*arg*/) - { - //SLANG_UNREACHABLE("visitGenericConstraintDeclRefType in EmitVisitor"); - } - void visitBasicExpressionType(BasicExpressionType* basicType, TypeEmitArg const& arg) { auto declarator = arg.declarator; @@ -2925,7 +2916,7 @@ struct EmitVisitor return; } - Substitutions* subst = declRef.substitutions.Ptr(); + GenericSubstitution* subst = declRef.substitutions.As().Ptr(); if (!subst) return; diff --git a/source/slang/ir.cpp b/source/slang/ir.cpp index 84ab3d9a5..5f3ca6c62 100644 --- a/source/slang/ir.cpp +++ b/source/slang/ir.cpp @@ -178,27 +178,27 @@ namespace Slang // // Add an instruction to a specific parent - void IRBuilder::addInst(IRBlock* block, IRInst* inst) + void IRBuilder::addInst(IRBlock* pblock, IRInst* inst) { - inst->parent = block; + inst->parent = pblock; - if (!block->firstInst) + if (!pblock->firstInst) { inst->prev = nullptr; inst->next = nullptr; - block->firstInst = inst; - block->lastInst = inst; + pblock->firstInst = inst; + pblock->lastInst = inst; } else { - auto prev = block->lastInst; + auto prev = pblock->lastInst; inst->prev = prev; inst->next = nullptr; prev->next = inst; - block->lastInst = inst; + pblock->lastInst = inst; } } @@ -206,7 +206,6 @@ namespace Slang void IRBuilder::addInst( IRInst* inst) { - auto insertBefore = insertBeforeInst; if(insertBeforeInst) { inst->insertBefore(insertBeforeInst); @@ -221,7 +220,7 @@ namespace Slang } static IRValue* createValueImpl( - IRBuilder* builder, + IRBuilder* /*builder*/, UInt size, IROp op, IRType* type) @@ -249,7 +248,7 @@ namespace Slang // arguments *after* the type (which is a mandatory // argument for all instructions). static IRInst* createInstImpl( - IRBuilder* builder, + IRBuilder* /*builder*/, UInt size, IROp op, IRType* type, @@ -261,8 +260,7 @@ namespace Slang IRInst* inst = (IRInst*) malloc(size); memset(inst, 0, size); - auto module = builder->getModule(); - inst->argCount = fixedArgCount + varArgCount; + inst->argCount = (uint32_t)(fixedArgCount + varArgCount); inst->op = op; @@ -632,7 +630,7 @@ namespace Slang IRInst* IRBuilder::emitCallInst( IRType* type, - IRValue* func, + IRValue* pFunc, UInt argCount, IRValue* const* args) { @@ -641,7 +639,7 @@ namespace Slang kIROp_Call, type, 1, - &func, + &pFunc, argCount, args); addInst(inst); @@ -829,12 +827,12 @@ namespace Slang IRFunc* IRBuilder::createFunc() { - IRFunc* func = createValue( + IRFunc* rsFunc = createValue( this, kIROp_Func, nullptr); - addGlobalValue(getModule(), func); - return func; + addGlobalValue(getModule(), rsFunc); + return rsFunc; } IRGlobalVar* IRBuilder::createGlobalVar( @@ -1129,13 +1127,13 @@ namespace Slang } IRInst* IRBuilder::emitBranch( - IRBlock* block) + IRBlock* pBlock) { auto inst = createInst( this, kIROp_unconditionalBranch, nullptr, - block); + pBlock); addInst(inst); return inst; } @@ -1543,7 +1541,7 @@ namespace Slang if(genericParentDeclRef) { - auto subst = declRef.substitutions; + auto subst = declRef.substitutions.As(); if( !subst || subst->genericDecl != genericParentDeclRef.getDecl() ) { // No actual substitutions in place here @@ -1698,6 +1696,7 @@ namespace Slang dumpChildrenRaw(context, block); } +#if 0 static void dumpChildrenRaw( IRDumpContext* context, IRFunc* func) @@ -1720,6 +1719,7 @@ namespace Slang dumpIndent(context); dump(context, "}\n"); } +#endif static void dumpInst( IRDumpContext* context, @@ -2239,8 +2239,8 @@ namespace Slang void IRInst::removeArguments() { - UInt argCount = this->argCount; - for( UInt aa = 0; aa < argCount; ++aa ) + UInt oldArgCount = this->argCount; + for( UInt aa = 0; aa < oldArgCount; ++aa ) { IRUse& use = getArgs()[aa]; @@ -2384,9 +2384,9 @@ namespace Slang IRBuilder* builder, Type* type, VarLayout* varLayout, - TypeLayout* typeLayout, - LayoutResourceKind kind, - GlobalVaryingDeclarator* declarator) + TypeLayout* /*typeLayout*/, + LayoutResourceKind /*kind*/, + GlobalVaryingDeclarator* /*declarator*/) { // TODO: We might be creating an `in` or `out` variable based on // an `in out` function parameter. In this case we should @@ -2550,7 +2550,6 @@ namespace Slang default: SLANG_UNEXPECTED("unimplemented"); - return ScalarizedVal(); } } @@ -3079,7 +3078,6 @@ namespace Slang break; default: SLANG_UNEXPECTED("no value registered for IR value"); - return nullptr; } } @@ -3111,18 +3109,27 @@ namespace Slang { if (!subst) return nullptr; + if (auto genSubst = dynamic_cast(subst)) + { + RefPtr newSubst = new GenericSubstitution(); + newSubst->outer = cloneSubstitutions(context, subst->outer); + newSubst->genericDecl = genSubst->genericDecl; - RefPtr newSubst = new Substitutions(); - newSubst->outer = cloneSubstitutions(context, subst->outer); - newSubst->genericDecl = subst->genericDecl; - - for (auto arg : subst->args) + for (auto arg : genSubst->args) + { + auto newArg = cloneSubstitutionArg(context, arg); + newSubst->args.Add(arg); + } + return newSubst; + } + else if (auto thisSubst = dynamic_cast(subst)) { - auto newArg = cloneSubstitutionArg(context, arg); - newSubst->args.Add(arg); + RefPtr newSubst = new ThisTypeSubstitution(); + newSubst->sourceType = thisSubst->sourceType; + newSubst->outer = cloneSubstitutions(context, subst->outer); + return newSubst; } - - return newSubst; + return nullptr; } DeclRef IRSpecContext::maybeCloneDeclRef(DeclRef const& declRef) @@ -3231,7 +3238,7 @@ namespace Slang { auto clonedKey = context->maybeCloneValue(originalEntry->requirementKey.usedValue); auto clonedVal = context->maybeCloneValue(originalEntry->satisfyingVal.usedValue); - auto clonedEntry = context->builder->createWitnessTableEntry( + context->builder->createWitnessTableEntry( clonedTable, clonedKey, clonedVal); @@ -3416,7 +3423,6 @@ namespace Slang default: SLANG_UNEXPECTED("unhandled case"); - return "unknown"; } } @@ -3518,7 +3524,6 @@ namespace Slang { // This shouldn't happen! SLANG_UNEXPECTED("no matching function registered"); - return cloneSimpleFunc(context, originalFunc); } // We will try to track the "best" definition we can find. @@ -3748,7 +3753,6 @@ namespace Slang else { SLANG_UNEXPECTED("unimplemented"); - return nullptr; } } @@ -3756,7 +3760,8 @@ namespace Slang IRGenericSpecContext* context, DeclRef declRef) { - auto subst = context->subst; + auto subst = context->subst.As(); + SLANG_ASSERT(subst); auto genericDecl = subst->genericDecl; UInt orinaryParamCount = 0; @@ -3806,12 +3811,13 @@ namespace Slang { auto declRefVal = (IRDeclRef*) originalVal; auto declRef = declRefVal->declRef; - + auto genSubst = subst.As(); + SLANG_ASSERT(genSubst); // We may have a direct reference to one of the parameters // of the generic we are specializing, and in that case // we nee to translate it over to the equiavalent of // the `Val` we have been given. - if(declRef.getDecl()->ParentDecl == subst->genericDecl) + if(declRef.getDecl()->ParentDecl == genSubst->genericDecl) { return getSubstValue(this, declRef); } @@ -3866,9 +3872,10 @@ namespace Slang // using a different overload of a target-specific function, // so we need to create a dummy substitution here, to make // sure it used the correct generic. - RefPtr newSubst = new Substitutions(); + RefPtr newSubst = new GenericSubstitution(); newSubst->genericDecl = genericFunc->genericDecl; - newSubst->args = specDeclRef.substitutions->args; + auto specDeclRefSubst = specDeclRef.substitutions.As(); + newSubst->args = specDeclRefSubst->args; IRGenericSpecContext context; context.shared = sharedContext; diff --git a/source/slang/lookup.cpp b/source/slang/lookup.cpp index b97dac560..a5425074f 100644 --- a/source/slang/lookup.cpp +++ b/source/slang/lookup.cpp @@ -452,28 +452,28 @@ void lookUpMemberImpl( lookUpMemberImpl(session, semantics, name, bound, ioResult, &breadcrumb); } } - } - else if (auto assocTypeDeclRefType = type->As()) - { - auto assocTypeDeclRef = assocTypeDeclRefType->declRef; - for (auto constraintDeclRef : getMembersOfType(assocTypeDeclRef)) + else if (auto assocTypeDeclRef = declRef.As()) { - // The super-type in the constraint (e.g., `Foo` in `T : Foo`) - // will tell us a type we should use for lookup. - auto bound = GetSup(constraintDeclRef); + for (auto constraintDeclRef : getMembersOfType(assocTypeDeclRef)) + { + // The super-type in the constraint (e.g., `Foo` in `T : Foo`) + // will tell us a type we should use for lookup. + auto bound = GetSup(constraintDeclRef); - // Go ahead and use the target type, with an appropriate breadcrumb - // to indicate that we indirected through a type constraint. + // Go ahead and use the target type, with an appropriate breadcrumb + // to indicate that we indirected through a type constraint. - BreadcrumbInfo breadcrumb; - breadcrumb.prev = inBreadcrumbs; - breadcrumb.kind = LookupResultItem::Breadcrumb::Kind::Constraint; - breadcrumb.declRef = constraintDeclRef; + BreadcrumbInfo breadcrumb; + breadcrumb.prev = inBreadcrumbs; + breadcrumb.kind = LookupResultItem::Breadcrumb::Kind::Constraint; + breadcrumb.declRef = constraintDeclRef; - // TODO: Need to consider case where this might recurse infinitely. - lookUpMemberImpl(session, semantics, name, bound, ioResult, &breadcrumb); + // TODO: Need to consider case where this might recurse infinitely. + lookUpMemberImpl(session, semantics, name, bound, ioResult, &breadcrumb); + } } } + } LookupResult lookUpMember( diff --git a/source/slang/lower-to-ir.cpp b/source/slang/lower-to-ir.cpp index 998197279..6099df1ed 100644 --- a/source/slang/lower-to-ir.cpp +++ b/source/slang/lower-to-ir.cpp @@ -870,9 +870,12 @@ struct ValLoweringVisitor : ValVisitorargs) + if (auto genSubst = subs.As()) { - (*ioArgs).Add(getSimpleVal(context, lowerVal(context, aa))); + for (auto aa : genSubst->args) + { + (*ioArgs).Add(getSimpleVal(context, lowerVal(context, aa))); + } } subs = subs->outer; } @@ -3037,24 +3040,33 @@ RefPtr lowerSubstitutions( { if(!subst) return nullptr; + RefPtr result; + if (auto genSubst = dynamic_cast(subst)) + { + RefPtr newSubst = new GenericSubstitution(); + newSubst->genericDecl = genSubst->genericDecl; + + for (auto arg : genSubst->args) + { + auto newArg = lowerSubstitutionArg(context, arg); + newSubst->args.Add(newArg); + } - RefPtr newSubst = new Substitutions(); + result = newSubst; + } + else if (auto thisSubst = dynamic_cast(subst)) + { + RefPtr newSubst = new ThisTypeSubstitution(); + newSubst->sourceType = lowerSubstitutionArg(context, thisSubst->sourceType); + result = newSubst; + } if (subst->outer) { - newSubst->outer = lowerSubstitutions( + result->outer = lowerSubstitutions( context, subst->outer); } - - newSubst->genericDecl = subst->genericDecl; - - for (auto arg : subst->args) - { - auto newArg = lowerSubstitutionArg(context, arg); - newSubst->args.Add(newArg); - } - - return newSubst; + return result; } LoweredValInfo emitDeclRef( diff --git a/source/slang/lower.cpp b/source/slang/lower.cpp index b810d9643..b8696df47 100644 --- a/source/slang/lower.cpp +++ b/source/slang/lower.cpp @@ -779,20 +779,6 @@ struct LoweringVisitor translateDeclRef(DeclRef(type->declRef)).As()); } - RefPtr visitGenericConstraintDeclRefType(GenericConstraintDeclRefType* type) - { - // not supported by lowering - SLANG_UNREACHABLE("visitGenericConstraintDeclRefType in LowerVisitor"); - return nullptr; - } - - RefPtr visitAssocTypeDeclRefType(AssocTypeDeclRefType* type) - { - // not supported by lowering - SLANG_UNREACHABLE("visitAssocTypeDeclRefType in LowerVisitor"); - return nullptr; - } - RefPtr visitTypeType(TypeType* type) { return getTypeType(lowerType(type->type)); @@ -2569,14 +2555,23 @@ struct LoweringVisitor Substitutions* inSubstitutions) { if (!inSubstitutions) return nullptr; - - RefPtr result = new Substitutions(); - result->genericDecl = translateDeclRef(inSubstitutions->genericDecl).As(); - for (auto arg : inSubstitutions->args) + if (auto genSubst = dynamic_cast(inSubstitutions)) { - result->args.Add(translateVal(arg)); + RefPtr result = new GenericSubstitution(); + result->genericDecl = translateDeclRef(genSubst->genericDecl).As(); + for (auto arg : genSubst->args) + { + result->args.Add(translateVal(arg)); + } + return result; } - return result; + else if (auto thisSubst = dynamic_cast(inSubstitutions)) + { + RefPtr result = new ThisTypeSubstitution(); + result->sourceType = translateVal(result->sourceType); + return result; + } + return nullptr; } static Decl* getModifiedDecl(Decl* decl) @@ -2733,7 +2728,11 @@ struct LoweringVisitor RefPtr tryToFindLayout( Decl* decl) { - auto loweredParent = translateDeclRef(decl->ParentDecl); + RefPtr loweredParent; + if (auto genericParentDecl = decl->ParentDecl->As()) + loweredParent = translateDeclRef(genericParentDecl->ParentDecl); + else + loweredParent = translateDeclRef(decl->ParentDecl); if (loweredParent) { auto layoutMod = loweredParent->FindModifier(); @@ -3831,7 +3830,7 @@ struct LoweringVisitor "Vector").As(); auto vectorTypeDecl = vectorGenericDecl->inner; - auto substitutions = new Substitutions(); + auto substitutions = new GenericSubstitution(); substitutions->genericDecl = vectorGenericDecl.Ptr(); substitutions->args.Add(elementType); substitutions->args.Add(elementCount); diff --git a/source/slang/mangle.cpp b/source/slang/mangle.cpp index cd90a0e41..bde4e12c7 100644 --- a/source/slang/mangle.cpp +++ b/source/slang/mangle.cpp @@ -117,10 +117,6 @@ namespace Slang { emitQualifiedName(context, declRefType->declRef); } - else if (auto assocTypeDeclRefType = dynamic_cast(type)) - { - emitQualifiedName(context, assocTypeDeclRefType->declRef); - } else { SLANG_UNEXPECTED("unimplemented case in mangling"); @@ -199,7 +195,7 @@ namespace Slang // There are two cases here: either we have specializations // in place for the parent generic declaration, or we don't. - auto subst = declRef.substitutions; + auto subst = declRef.substitutions.As(); if( subst && subst->genericDecl == parentGenericDeclRef.getDecl() ) { // This is the case where we *do* have substitutions. diff --git a/source/slang/slang.natvis b/source/slang/slang.natvis index 7a7f7fe0e..7e6fd3753 100644 --- a/source/slang/slang.natvis +++ b/source/slang/slang.natvis @@ -9,5 +9,30 @@ rawVal ? ($T1*)((char*)this + rawVal) : ($T1*)0 - + + decl ? ($T1*)(decl) : ($T1*)0 + DeclRef nullptr + DeclRef {(*(*(Slang::DeclRefBase*)this).decl).nameAndLoc} + + decl ? ($T1*)(decl) : ($T1*)0 + "=========================" + + substitutions.pointer + outer.pointer + this + + + + + DeclRefType {declRef} + + declRef + + + + {{name={(char*)(text.buffer.pointer+1), s}}} + + + {{name={(char*)((*name).text.buffer.pointer+1), s} loc={loc.raw}}} + \ No newline at end of file diff --git a/source/slang/syntax-base-defs.h b/source/slang/syntax-base-defs.h index 8a22a61d2..3c7e8c5ae 100644 --- a/source/slang/syntax-base-defs.h +++ b/source/slang/syntax-base-defs.h @@ -126,31 +126,44 @@ protected: ) END_SYNTAX_CLASS() + // A substitution represents a binding of certain // type-level variables to concrete argument values -SYNTAX_CLASS(Substitutions, RefObject) +ABSTRACT_SYNTAX_CLASS(Substitutions, RefObject) + + // Any further substitutions, relating to outer generic declarations + SYNTAX_FIELD(RefPtr, outer) + + RAW( + // Apply a set of substitutions to the bindings in this substitution + virtual RefPtr SubstituteImpl(Substitutions* subst, int* ioDiff) = 0; + // Check if these are equivalent substitutiosn to another set + virtual bool Equals(Substitutions* subst) = 0; + virtual bool operator == (const Substitutions & subst) = 0; + virtual int GetHashCode() const = 0; + ) +END_SYNTAX_CLASS() + +SYNTAX_CLASS(GenericSubstitution, Substitutions) // The generic declaration that defines the // parametesr we are binding to arguments - DECL_FIELD(GenericDecl*, genericDecl) + DECL_FIELD(GenericDecl*, genericDecl) // The actual values of the arguments SYNTAX_FIELD(List>, args) - - // Any further substitutions, relating to outer generic declarations - SYNTAX_FIELD(RefPtr, outer) - + RAW( // Apply a set of substitutions to the bindings in this substitution - RefPtr SubstituteImpl(Substitutions* subst, int* ioDiff); + virtual RefPtr SubstituteImpl(Substitutions* subst, int* ioDiff) override; // Check if these are equivalent substitutiosn to another set - bool Equals(Substitutions* subst); - bool operator == (const Substitutions & subst) + virtual bool Equals(Substitutions* subst) override; + virtual bool operator == (const Substitutions & subst) override { return Equals(const_cast(&subst)); } - int GetHashCode() const + virtual int GetHashCode() const override { int rs = 0; for (auto && v : args) @@ -163,6 +176,27 @@ SYNTAX_CLASS(Substitutions, RefObject) ) END_SYNTAX_CLASS() +SYNTAX_CLASS(ThisTypeSubstitution, Substitutions) + // The actual type that provides the lookup scope for an associated type + SYNTAX_FIELD(RefPtr, sourceType) + + RAW( + // Apply a set of substitutions to the bindings in this substitution + virtual RefPtr SubstituteImpl(Substitutions* subst, int* ioDiff) override; + + // Check if these are equivalent substitutiosn to another set + virtual bool Equals(Substitutions* subst) override; + virtual bool operator == (const Substitutions & subst) override + { + return Equals(const_cast(&subst)); + } + virtual int GetHashCode() const override + { + return sourceType->GetHashCode(); + } + ) +END_SYNTAX_CLASS() + ABSTRACT_SYNTAX_CLASS(SyntaxNode, SyntaxNodeBase) END_SYNTAX_CLASS() diff --git a/source/slang/syntax.cpp b/source/slang/syntax.cpp index 3e38955ba..a3a5fdcb6 100644 --- a/source/slang/syntax.cpp +++ b/source/slang/syntax.cpp @@ -91,6 +91,8 @@ ABSTRACT_SYNTAX_CLASS(Modifier, SyntaxNodeBase); ABSTRACT_SYNTAX_CLASS(Expr, SyntaxNode); ABSTRACT_SYNTAX_CLASS(Substitutions, SyntaxNode); +ABSTRACT_SYNTAX_CLASS(GenericSubstitution, Substitutions); +ABSTRACT_SYNTAX_CLASS(ThisTypeSubstitution, Substitutions); #include "expr-defs.h" #include "decl-defs.h" @@ -98,8 +100,6 @@ ABSTRACT_SYNTAX_CLASS(Substitutions, SyntaxNode); #include "stmt-defs.h" #include "type-defs.h" #include "val-defs.h" - - #include "object-meta-end.h" bool SyntaxClassBase::isSubClassOfImpl(SyntaxClassBase const& super) const @@ -283,7 +283,7 @@ void Type::accept(IValVisitor* visitor, void* extra) this, "PtrType").As(); auto typeDecl = genericDecl->inner; - auto substitutions = new Substitutions(); + auto substitutions = new GenericSubstitution(); substitutions->genericDecl = genericDecl.Ptr(); substitutions->args.Add(valueType); @@ -414,38 +414,57 @@ void Type::accept(IValVisitor* visitor, void* extra) // search for a substitution that might apply to us for (auto s = subst; s; s = s->outer.Ptr()) { - // the generic decl associated with the substitution list must be - // the generic decl that declared this parameter - auto genericDecl = s->genericDecl; - if (genericDecl != genericTypeParamDecl->ParentDecl) - continue; - - int index = 0; - for (auto m : genericDecl->Members) + if (auto genericSubst = dynamic_cast(s)) { - if (m.Ptr() == genericTypeParamDecl) - { - // We've found it, so return the corresponding specialization argument - (*ioDiff)++; - return s->args[index]; - } - else if(auto typeParam = m.As()) + // the generic decl associated with the substitution list must be + // the generic decl that declared this parameter + auto genericDecl = genericSubst->genericDecl; + if (genericDecl != genericTypeParamDecl->ParentDecl) + continue; + + int index = 0; + for (auto m : genericDecl->Members) { - index++; - } - else if(auto valParam = m.As()) - { - index++; + if (m.Ptr() == genericTypeParamDecl) + { + // We've found it, so return the corresponding specialization argument + (*ioDiff)++; + return genericSubst->args[index]; + } + else if (auto typeParam = m.As()) + { + index++; + } + else if (auto valParam = m.As()) + { + index++; + } + else + { + } } - else + } + + } + } + // the second case we care about is when this decl type refers to an associatedtype decl + // we want to replace it with the actual associated type + else if (auto assocTypeDecl = dynamic_cast(declRef.getDecl())) + { + // search for a substitution that might apply to us + for (auto s = subst; s; s = s->outer.Ptr()) + { + if (auto thisTypeSubst = dynamic_cast(s)) + { + if (auto aggTypeDeclRef = thisTypeSubst->sourceType.As()->declRef.As()) { + Decl * targetType = nullptr; + if (aggTypeDeclRef.getDecl()->memberDictionary.TryGetValue(assocTypeDecl->getName(), targetType)) + return DeclRefType::Create(this->getSession(), DeclRef(targetType, aggTypeDeclRef.substitutions)); } } - } } - - int diff = 0; DeclRef substDeclRef = declRef.SubstituteImpl(subst, &diff); @@ -486,10 +505,25 @@ void Type::accept(IValVisitor* visitor, void* extra) // we will construct a default specialization at the use // site if needed. - if( auto genericParent = declRef.GetParent().As() ) + if (auto genericParent = declRef.GetParent().As()) { auto subst = declRef.substitutions; - if( !subst || subst->genericDecl != genericParent.decl ) + // try find a substitution targeting this generic decl + bool substFound = false; + while (subst) + { + if (auto genSubst = dynamic_cast(subst.Ptr())) + { + if (genSubst->genericDecl == genericParent.decl) + { + substFound = true; + break; + } + } + subst = subst->outer; + } + // we did not find an existing substituion, create a default one + if (!substFound) { declRef.substitutions = createDefaultSubstitutions( session, @@ -507,7 +541,7 @@ void Type::accept(IValVisitor* visitor, void* extra) } else if (auto magicMod = declRef.getDecl()->FindModifier()) { - Substitutions* subst = declRef.substitutions.Ptr(); + GenericSubstitution* subst = declRef.substitutions.As().Ptr(); if (magicMod->name == "SamplerState") { @@ -761,7 +795,6 @@ void Type::accept(IValVisitor* visitor, void* extra) bool NamedExpressionType::EqualsImpl(Type * /*type*/) { SLANG_UNEXPECTED("unreachable"); - return false; } Type* NamedExpressionType::CreateCanonicalType() @@ -772,7 +805,6 @@ void Type::accept(IValVisitor* visitor, void* extra) int NamedExpressionType::GetHashCode() { SLANG_UNEXPECTED("unreachable"); - return 0; } // FuncType @@ -910,7 +942,6 @@ void Type::accept(IValVisitor* visitor, void* extra) int TypeType::GetHashCode() { SLANG_UNEXPECTED("unreachable"); - return 0; } // GenericDeclRefType @@ -940,125 +971,6 @@ void Type::accept(IValVisitor* visitor, void* extra) return this; } - // AssocTypeDeclRefType - - String AssocTypeDeclRefType::ToString() - { - // TODO: what is appropriate here? - return ""; - } - - bool AssocTypeDeclRefType::EqualsImpl(Type * type) - { - if (auto assocTypeDeclRefType = type->As()) - { - return declRef.Equals(assocTypeDeclRefType->declRef); - } - return false; - } - - RefPtr AssocTypeDeclRefType::SubstituteImpl(Substitutions* subst, int* ioDiff) - { - if (!sourceType) - return this; - auto substSourceType = sourceType->SubstituteImpl(subst, ioDiff); - if (auto parentDeclRefType = substSourceType.As()) - { - auto parentDeclRef = parentDeclRefType->declRef; - DeclRef newParentDeclRef = parentDeclRef.As(); - // search for a substitution that might apply to us - for (auto s = subst; s; s = s->outer.Ptr()) - { - // the generic decl associated with the substitution list must be - // the generic decl that declared this parameter - auto genericDecl = s->genericDecl; - if (genericDecl != parentDeclRef.getDecl()->ParentDecl) - continue; - int index = 0; - for (auto m : genericDecl->Members) - { - if (m.Ptr() == parentDeclRef.getDecl()) - { - // We've found it, so return the corresponding specialization argument - (*ioDiff)++; - if (auto declRef = s->args[index].As()) - { - newParentDeclRef = (*declRef).declRef.As(); - goto searchEnd; - } - } - else if (auto typeParam = m.As()) - { - index++; - } - else if (auto valParam = m.As()) - { - index++; - } - else - { - } - } - } - searchEnd: - if (newParentDeclRef) - { - Decl* targetTypeDecl = nullptr; - if (newParentDeclRef.getDecl()->memberDictionary.TryGetValue(this->GetDeclRef().decl->getName(), targetTypeDecl)) - { - if (auto typeDefDecl = targetTypeDecl->As()) - return GetType(DeclRef(typeDefDecl, subst)); - else - return DeclRefType::Create(this->getSession(), DeclRef(targetTypeDecl, subst)); - } - } - } - - return this; - } - - int AssocTypeDeclRefType::GetHashCode() - { - return declRef.GetHashCode(); - } - - Type* AssocTypeDeclRefType::CreateCanonicalType() - { - return this; - } - - // GenericConstraintDeclRefType - - String GenericConstraintDeclRefType::ToString() - { - // TODO: what is appropriate here? - return ""; - } - - bool GenericConstraintDeclRefType::EqualsImpl(Type * type) - { - if (auto other = type->As()) - { - return supType->Equals(other->supType) && subType->Equals(other->subType); - } - return false; - } - - RefPtr GenericConstraintDeclRefType::SubstituteImpl(Substitutions* subst, int* ioDiff) - { - return subType->SubstituteImpl(subst, ioDiff); - } - - int GenericConstraintDeclRefType::GetHashCode() - { - return combineHash(subType.GetHashCode(), supType.GetHashCode()); - } - - Type* GenericConstraintDeclRefType::CreateCanonicalType() - { - return this; - } - // ArithmeticExpressionType // VectorExpressionType @@ -1091,24 +1003,24 @@ void Type::accept(IValVisitor* visitor, void* extra) Type* MatrixExpressionType::getElementType() { - return this->declRef.substitutions->args[0].As().Ptr(); + return this->declRef.substitutions.As()->args[0].As().Ptr(); } IntVal* MatrixExpressionType::getRowCount() { - return this->declRef.substitutions->args[1].As().Ptr(); + return this->declRef.substitutions.As()->args[1].As().Ptr(); } IntVal* MatrixExpressionType::getColumnCount() { - return this->declRef.substitutions->args[2].As().Ptr(); + return this->declRef.substitutions.As()->args[2].As().Ptr(); } // PtrTypeBase Type* PtrTypeBase::getValueType() { - return this->declRef.substitutions->args[0].As().Ptr(); + return this->declRef.substitutions.As()->args[0].As().Ptr(); } // GenericParamIntVal @@ -1137,31 +1049,34 @@ void Type::accept(IValVisitor* visitor, void* extra) // search for a substitution that might apply to us for (auto s = subst; s; s = s->outer.Ptr()) { - // the generic decl associated with the substitution list must be - // the generic decl that declared this parameter - auto genericDecl = s->genericDecl; - if (genericDecl != declRef.getDecl()->ParentDecl) - continue; - - int index = 0; - for (auto m : genericDecl->Members) + if (auto genSubst = dynamic_cast(s)) { - if (m.Ptr() == declRef.getDecl()) - { - // We've found it, so return the corresponding specialization argument - (*ioDiff)++; - return s->args[index]; - } - else if(auto typeParam = m.As()) - { - index++; - } - else if(auto valParam = m.As()) - { - index++; - } - else + // the generic decl associated with the substitution list must be + // the generic decl that declared this parameter + auto genericDecl = genSubst->genericDecl; + if (genericDecl != declRef.getDecl()->ParentDecl) + continue; + + int index = 0; + for (auto m : genericDecl->Members) { + if (m.Ptr() == declRef.getDecl()) + { + // We've found it, so return the corresponding specialization argument + (*ioDiff)++; + return genSubst->args[index]; + } + else if (auto typeParam = m.As()) + { + index++; + } + else if (auto valParam = m.As()) + { + index++; + } + else + { + } } } } @@ -1172,12 +1087,12 @@ void Type::accept(IValVisitor* visitor, void* extra) // Substitutions - RefPtr Substitutions::SubstituteImpl(Substitutions* subst, int* ioDiff) + RefPtr GenericSubstitution::SubstituteImpl(Substitutions* subst, int* ioDiff) { if (!this) return nullptr; int diff = 0; - auto outerSubst = outer->SubstituteImpl(subst, &diff); + auto outerSubst = outer ? outer->SubstituteImpl(subst, &diff) : nullptr; List> substArgs; for (auto a : args) @@ -1188,35 +1103,73 @@ void Type::accept(IValVisitor* visitor, void* extra) if (!diff) return this; (*ioDiff)++; - auto substSubst = new Substitutions(); + auto substSubst = new GenericSubstitution(); substSubst->genericDecl = genericDecl; substSubst->args = substArgs; return substSubst; } - bool Substitutions::Equals(Substitutions* subst) + bool GenericSubstitution::Equals(Substitutions* subst) { // both must be NULL, or non-NULL if (!this || !subst) return !this && !subst; - - if (genericDecl != subst->genericDecl) + auto genericSubst = dynamic_cast(subst); + if (!genericSubst) + return false; + if (genericDecl != genericSubst->genericDecl) return false; UInt argCount = args.Count(); - SLANG_RELEASE_ASSERT(args.Count() == subst->args.Count()); + SLANG_RELEASE_ASSERT(args.Count() == genericSubst->args.Count()); for (UInt aa = 0; aa < argCount; ++aa) { - if (!args[aa]->EqualsVal(subst->args[aa].Ptr())) + if (!args[aa]->EqualsVal(genericSubst->args[aa].Ptr())) return false; } + if (!outer) + return !subst->outer; + if (!outer->Equals(subst->outer.Ptr())) return false; return true; } + RefPtr ThisTypeSubstitution::SubstituteImpl(Substitutions* subst, int* ioDiff) + { + if (!this) return nullptr; + + int diff = 0; + auto outerSubst = outer->SubstituteImpl(subst, &diff); + + auto newSourceType = sourceType->SubstituteImpl(subst, ioDiff); + if (!diff) return this; + + (*ioDiff)++; + auto substSubst = new ThisTypeSubstitution(); + substSubst->sourceType = newSourceType; + substSubst->outer = outerSubst; + return substSubst; + } + + bool ThisTypeSubstitution::Equals(Substitutions* subst) + { + // both must be NULL, or non-NULL + if (!this || !subst) + return !this && !subst; + auto thisSubst = dynamic_cast(subst); + if (!thisSubst) + return false; + if (!thisSubst->sourceType->EqualsVal(sourceType)) + return false; + if (!outer->Equals(subst->outer.Ptr())) + return false; + return true; + } + + // DeclRefBase @@ -1248,8 +1201,6 @@ void Type::accept(IValVisitor* visitor, void* extra) return expr; SLANG_UNIMPLEMENTED_X("generic substitution into expressions"); - - return expr; } @@ -1277,7 +1228,8 @@ void Type::accept(IValVisitor* visitor, void* extra) { if (decl != declRef.decl) return false; - + if (!substitutions) + return !declRef.substitutions; if (!substitutions->Equals(declRef.substitutions.Ptr())) return false; @@ -1298,7 +1250,8 @@ void Type::accept(IValVisitor* visitor, void* extra) if (auto parentGeneric = dynamic_cast(parentDecl)) { - if (substitutions && substitutions->genericDecl == parentDecl) + auto genSubst = substitutions.As(); + if (genSubst && genSubst->genericDecl == parentDecl) { // We strip away the specializations that were applied to // the parent, since we were asked for a reference *to* the parent. @@ -1427,7 +1380,6 @@ void Type::accept(IValVisitor* visitor, void* extra) else { SLANG_UNEXPECTED("unhandled syntax class name"); - return nullptr; } } @@ -1437,12 +1389,12 @@ void Type::accept(IValVisitor* visitor, void* extra) Type* HLSLPatchType::getElementType() { - return this->declRef.substitutions->args[0].As().Ptr(); + return this->declRef.substitutions.As()->args[0].As().Ptr(); } IntVal* HLSLPatchType::getElementCount() { - return this->declRef.substitutions->args[1].As().Ptr(); + return this->declRef.substitutions.As()->args[1].As().Ptr(); } // Constructors for types diff --git a/source/slang/type-defs.h b/source/slang/type-defs.h index 2052e1eb8..60f519c82 100644 --- a/source/slang/type-defs.h +++ b/source/slang/type-defs.h @@ -489,59 +489,4 @@ protected: virtual int GetHashCode() override; virtual Type* CreateCanonicalType() override; ) -END_SYNTAX_CLASS() - -// The "type" of an expression that references a asscoiated type decl (via 'assoctype' keyword). -SYNTAX_CLASS(AssocTypeDeclRefType, Type) - DECL_FIELD(DeclRef, declRef) - DECL_FIELD(RefPtr, sourceType) - RAW( - AssocTypeDeclRefType() - {} - AssocTypeDeclRefType( - DeclRef declRef) - : declRef(declRef) - {} - - - DeclRef const& GetDeclRef() const { return declRef; } - - virtual String ToString() override; - - protected: - virtual RefPtr SubstituteImpl(Substitutions* subst, int* ioDiff) override; - virtual bool EqualsImpl(Type * type) override; - virtual int GetHashCode() override; - virtual Type* CreateCanonicalType() override; - ) -END_SYNTAX_CLASS() - -// The "type" of an generic constraint, which wraps both the sub and sup (interface) type -// the sub type can be used in associated type substitution in later type evaluation -SYNTAX_CLASS(GenericConstraintDeclRefType, Type) - DECL_FIELD(RefPtr, subType) - DECL_FIELD(RefPtr, supType) -RAW( - GenericConstraintDeclRefType() - {} - GenericConstraintDeclRefType(Session* session, - RefPtr sub, - RefPtr sup) - : subType(sub), supType(sup) - { - setSession(session); - } - - - RefPtr const& GetSupType() const { return supType; } - RefPtr const& GetSubType() const { return subType; } - - virtual String ToString() override; - - protected: - virtual RefPtr SubstituteImpl(Substitutions* subst, int* ioDiff) override; - virtual bool EqualsImpl(Type * type) override; - virtual int GetHashCode() override; - virtual Type* CreateCanonicalType() override; -) END_SYNTAX_CLASS() \ No newline at end of file diff --git a/source/slang/vm.cpp b/source/slang/vm.cpp index f129d15e0..d5bacaa36 100644 --- a/source/slang/vm.cpp +++ b/source/slang/vm.cpp @@ -513,8 +513,8 @@ void computeTypeSizeAlign( break; default: - SLANG_UNIMPLEMENTED_X("type sizing"); impl->size = 0; + SLANG_UNIMPLEMENTED_X("type sizing"); break; } @@ -528,7 +528,7 @@ void computeTypeSizeAlign( } VMType getType( - VM* vm, + VM* /*vm*/, VMTypeImpl* typeImpl) { // TODO: need to look up an existing type that matches... @@ -587,7 +587,7 @@ VMType loadVMType( VMTypeImpl* impl = (VMTypeImpl*) alloca(size); memset(impl, 0, size); impl->op = bcType->op; - impl->argCount = argCount; + impl->argCount = (uint32_t)argCount; VMVal* args = (VMVal*) (impl + 1); for(UInt aa = 0; aa < argCount; ++aa) @@ -597,14 +597,11 @@ VMType loadVMType( return getType(vmModule->vm, impl); } - - SLANG_UNEXPECTED("unimplemented"); - return VMType(); break; } } -void* allocateImpl(VM* vm, UInt size, UInt align) +void* allocateImpl(VM* /*vm*/, UInt size, UInt /*align*/) { void* ptr = malloc(size); memset(ptr, 0, size); @@ -666,7 +663,7 @@ void* loadVMSymbol( VMModule* loadVMModuleInstance( VM* vm, void const* bytecode, - size_t bytecodeSize) + size_t /*bytecodeSize*/) { BCHeader* bcHeader = (BCHeader*) bytecode; @@ -732,14 +729,14 @@ void* findGlobalSymbolPtr( continue; if(strcmp(symbolName, name) == 0) - return getGlobalPtr(module, ss); + return getGlobalPtr(module, (uint32_t)ss); } return nullptr; } VMThread* createThread( - VM* vm) + VM* /*vm*/) { VMThread* thread = new VMThread(); thread->frame = nullptr; @@ -863,7 +860,7 @@ void resumeThread( case kIROp_BufferStore: { VMType resultType = decodeType(frame, &ip); - UInt argCount = decodeUInt(&ip); + /*UInt argCount =*/ decodeUInt(&ip); char* bufferData = decodeOperand(frame, &ip); uint32_t index = decodeOperand(frame, &ip); @@ -944,10 +941,9 @@ void resumeThread( case kIROp_ReturnVal: { VMType instType = decodeType(frame, &ip); - UInt argCount = decodeUInt(&ip); + /*UInt argCount =*/ decodeUInt(&ip); void* argPtr = decodeOperandPtr(frame, &ip); - VMFrame* oldFrame = frame; VMFrame* newFrame = frame->parent; vmThread->frame = newFrame; @@ -980,7 +976,7 @@ void resumeThread( Int destinationBlock = decodeSInt(&ip); for( UInt aa = 2; aa < argCount; ++aa ) { - void* argPtr = decodeOperandPtr(frame, &ip); + decodeOperandPtr(frame, &ip); } // TODO: we need to deal with the case of @@ -1006,7 +1002,7 @@ void resumeThread( Int falseBlockID = decodeSInt(&ip); for( UInt aa = 4; aa < argCount; ++aa ) { - void* argPtr = decodeOperandPtr(frame, &ip); + decodeOperandPtr(frame, &ip); } Int destinationBlock = *condition ? trueBlockID : falseBlockID; @@ -1025,7 +1021,7 @@ void resumeThread( // knowing too much about an instruction... VMType resultType = decodeType(frame, &ip); - UInt argCount = decodeUInt(&ip); + /*UInt argCount =*/ decodeUInt(&ip); void* argPtrs[16] = { 0 }; auto leftOpnd = decodeOperandPtrAndType(frame, &ip); auto type = leftOpnd.type; @@ -1050,7 +1046,7 @@ void resumeThread( case kIROp_Mul: { VMType type = decodeType(frame, &ip); - UInt argCount = decodeUInt(&ip); + /*UInt argCount =*/ decodeUInt(&ip); void* leftPtr = decodeOperandPtr(frame, &ip); void* rightPtr = decodeOperandPtr(frame, &ip); @@ -1072,7 +1068,7 @@ void resumeThread( case kIROp_Sub: { VMType type = decodeType(frame, &ip); - UInt argCount = decodeUInt(&ip); + /*UInt argCount =*/ decodeUInt(&ip); void* leftPtr = decodeOperandPtr(frame, &ip); void* rightPtr = decodeOperandPtr(frame, &ip); diff --git a/tests/compute/assoctype-complex.slang b/tests/compute/assoctype-complex.slang index de3f1a103..f29d231b6 100644 --- a/tests/compute/assoctype-complex.slang +++ b/tests/compute/assoctype-complex.slang @@ -30,30 +30,18 @@ struct Simple : ISimple return v0.sub(4, v1.sub(1,2)); } }; -/* + __generic T.U.V test(T simple, T.U v0, T.U v1) { return simple.add(v0, v1); } -__generic -T test(T v0, T v1) -{ - return v0 + v1; -} -*/ -__generic -T test(T v0, T v1) -{ - return T(3.0); -} [numthreads(4, 1, 1)] void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID) { - //Simple s; - //Val v0, v1; - //float outVal = test(s, v0, v1); // == 1.0 - float outVal = test(1.0, 2.0); + Simple s; + Val v0, v1; + float outVal = test(s, v0, v1); // == 1.0 outputBuffer[dispatchThreadID.x] = outVal; } \ No newline at end of file diff --git a/tests/compute/generics-constraint1.slang b/tests/compute/generics-constraint1.slang index ff90c1cc9..aa8d398e8 100644 --- a/tests/compute/generics-constraint1.slang +++ b/tests/compute/generics-constraint1.slang @@ -6,7 +6,7 @@ RWStructuredBuffer outputBuffer; __generic T test(T v0, T v1) { - return T(3.0); + return v0; } [numthreads(4, 1, 1)] diff --git a/tests/compute/generics-constructor.slang b/tests/compute/generics-constructor.slang new file mode 100644 index 000000000..c7473cc8b --- /dev/null +++ b/tests/compute/generics-constructor.slang @@ -0,0 +1,17 @@ +//TEST(smoke, compute):COMPARE_COMPUTE:-xslang -use-ir +//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out + +RWStructuredBuffer outputBuffer; + +__generic +T test(T v0, T v1) +{ + return T(3.0); +} + +[numthreads(4, 1, 1)] +void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID) +{ + float outVal = test(1.0, 2.0); + outputBuffer[dispatchThreadID.x] = outVal; +} \ No newline at end of file -- cgit v1.2.3 From 0a3656788473244b4760791c4129a4080a6631f6 Mon Sep 17 00:00:00 2001 From: Yong He Date: Fri, 3 Nov 2017 18:55:03 -0400 Subject: associatedtypes: generating almost correct HLSL, but is not calling correctly mangled function. --- source/slang/check.cpp | 157 +++++++++++++++++++++++++++++++++++++++---- source/slang/emit.cpp | 5 ++ source/slang/lower-to-ir.cpp | 7 ++ source/slang/lower.cpp | 4 ++ source/slang/slang.cpp | 1 + source/slang/slang.natvis | 21 ++++++ source/slang/syntax.cpp | 120 ++++++++++++++++++++++++++++++--- source/slang/syntax.h | 3 +- source/slang/type-defs.h | 32 +++++++++ 9 files changed, 329 insertions(+), 21 deletions(-) (limited to 'source/slang/check.cpp') 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; - + DeclRef *declRefOut; if (baseExpr->type->As()) { 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()) { RefPtr subst = new ThisTypeSubstitution(); - subst->sourceType = baseExpr->type.type; + auto baseDeclRefType = baseExpr->type.type.As(); + if (baseDeclRefType && !baseDeclRefType->declRef.getDecl()->As()) + { + // 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()) subst->sourceType = typeType->type; expr->type = GetTypeForDeclRef(DeclRef(assocTypeDecl.getDecl(), subst)); + declRefOut->substitutions = subst; + return expr; } else if (auto constraintDecl = declRef.As()) { - expr->type = baseExpr->type; + expr = baseExpr; + if (auto declRefExpr = expr.As()) + declRefOut = &declRefExpr->declRef; + else + return expr; + RefPtr declRefType; + if (auto typeType = baseExpr->type.type.As()) + declRefType = typeType->type->As(); + else + declRefType = baseExpr->type.type.As(); + + if (declRefType) + { + RefPtr subst = new ThisTypeSubstitution(); + subst->sourceType = declRefType; + auto exprType = DeclRefType::Create(getSession(), DeclRef(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()) { + // propagate ThisTypeSubstitution + RefPtr declRefType; + if (auto typeType = baseExpr->type.type.As()) + declRefType = typeType->type->As(); + else + declRefType = baseExpr->type.type.As(); + RefPtr thisSubst; + if (declRefType) + { + auto subst = declRefType->declRef.substitutions; + while (subst) + { + thisSubst = subst.As(); + 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()) { auto toTypeDeclRef = toDeclRefType->declRef; - if (auto interfaceDeclRef = toTypeDeclRef.As()) + if (auto assocDeclRef = toTypeDeclRef.As()) + { + if (auto fromTypeDeclRefType = fromType->As()) + { + if (auto thisSubst = assocDeclRef.substitutions.As()) + { + if (auto fromThisSubst = fromTypeDeclRefType->declRef.substitutions.As()) + { + if (!thisSubst->sourceType || !fromThisSubst->sourceType) + return true; + if (CanCoerce(thisSubst->sourceType.As(), fromThisSubst->sourceType.As(), outCost)) + { + if (outCost) + *outCost = kConversionCost_CastToInterface; + if (outToExpr) + *outToExpr = fromExpr; + return true; + } + } + else + return true; + } + else + return true; + } + } + else if (auto interfaceDeclRef = toTypeDeclRef.As()) { // Trying to convert to an interface type. // @@ -927,8 +1017,42 @@ namespace Slang return true; } } - } + else if (auto genParamDeclRef = toTypeDeclRef.As()) + { + // 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(); + SLANG_ASSERT(genericDeclRef); + + for (auto constraintDeclRef : getMembersOfType(genericDeclRef)) + { + auto sub = GetSub(constraintDeclRef); + auto sup = GetSup(constraintDeclRef); + auto subDeclRef = sub->As(); + if (!subDeclRef) + continue; + if (subDeclRef->declRef != genParamDeclRef) + continue; + auto supDeclRefType = sup->As(); + if (supDeclRefType) + { + auto toInterfaceDeclRef = supDeclRefType->declRef.As(); + 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()->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()) @@ -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()->resultType; // GetResultType(funcDeclRef); + candidate.resultType = GetResultType(funcDeclRef); AddOverloadCandidate(context, candidate); } @@ -5739,6 +5863,9 @@ namespace Slang RefPtr visitInvokeExpr(InvokeExpr *expr) { + if (auto mbrExpr = expr->FunctionExpr->As()) + 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()) + { + 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 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()); } + RefPtr visitThisType(ThisType* type) + { + return type; + } RefPtr 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 @@ {{name={(char*)((*name).text.buffer.pointer+1), s} loc={loc.raw}}} + + + {{{op}}} + + op + argCount + + argCount + (IRUse*)(this + 1) + + + + + + + firstInst + (Slang::IRInst*)next + this + + + \ 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 ""; + } + + int ThisType::GetHashCode() + { + return 0; + } + + bool ThisType::EqualsImpl(Type * type) + { + return true; + } + + Type* ThisType::CreateCanonicalType() + { + // A declaration reference is already canonical + return this; + } + + RefPtr ThisType::SubstituteImpl(Substitutions* subst, int* ioDiff) + { + while (subst) + { + if (auto thisTypeSubst = dynamic_cast(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(type)) + return objectType->Equals(memberType->objectType.Ptr()) && declRef.Equals(memberType->declRef); + return false; + } + + Type* MemberType::CreateCanonicalType() + { + if (auto declRefType = objectType->As()) + { + if (auto aggDeclRef = declRefType->declRef.As()) + { + Decl* targetDecl = nullptr; + if (aggDeclRef.getDecl()->memberDictionary.TryGetValue(declRef.getDecl()->nameAndLoc.name, targetDecl)) + { + if (auto typeDefDecl = dynamic_cast(targetDecl)) + return typeDefDecl->type.type; + else + return DeclRefType::Create(getSession(), DeclRef(targetDecl, aggDeclRef.substitutions)); + } + } + } + return this; + } + + RefPtr 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(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()) { - if (auto thisTypeSubst = dynamic_cast(s)) + if (thisTypeSubst->sourceType) { if (auto aggTypeDeclRef = thisTypeSubst->sourceType.As()->declRef.As()) { Decl * targetType = nullptr; if (aggTypeDeclRef.getDecl()->memberDictionary.TryGetValue(assocTypeDecl->getName(), targetType)) - return DeclRefType::Create(this->getSession(), DeclRef(targetType, aggTypeDeclRef.substitutions)); + { + if (auto typeDefDecl = dynamic_cast(targetType)) + return typeDefDecl->type.type; + else + return DeclRefType::Create(getSession(), DeclRef(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 outerSubst; + if (outer) + outerSubst = outer->SubstituteImpl(subst, &diff); + RefPtr 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(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(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 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 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, objectType) + DECL_FIELD(DeclRef, declRef) + RAW( + virtual String ToString() override; + virtual RefPtr 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, declRef) -- cgit v1.2.3 From 76db3636418f1667db1c8b0d3b6cfec6c652cc84 Mon Sep 17 00:00:00 2001 From: Yong He Date: Sat, 4 Nov 2017 06:57:48 -0400 Subject: work in-progress --- source/slang/check.cpp | 181 +++++++++++++++++++++------------------------- source/slang/slang.natvis | 9 +++ source/slang/syntax.cpp | 18 +---- 3 files changed, 96 insertions(+), 112 deletions(-) (limited to 'source/slang/check.cpp') diff --git a/source/slang/check.cpp b/source/slang/check.cpp index 240ac2d05..8e504e783 100644 --- a/source/slang/check.cpp +++ b/source/slang/check.cpp @@ -140,6 +140,55 @@ namespace Slang return result; } + void insertSubstAtBottom(DeclRefBase & declRef, RefPtr substToInsert) + { + RefPtr lastSubst; + auto subst = declRef.substitutions; + while (subst) + { + if (subst) + lastSubst = subst; + subst = subst->outer; + } + if (lastSubst) + lastSubst->outer = substToInsert; + else + declRef.substitutions = substToInsert; + } + + RefPtr getThisTypeSubst(DeclRefBase & declRef, bool insertSubstEntry) + { + RefPtr thisSubst; + auto subst = declRef.substitutions; + while (subst) + { + if (auto s = subst.As()) + { + thisSubst = s; + break; + } + subst = subst->outer; + } + if (!thisSubst) + { + thisSubst = new ThisTypeSubstitution(); + if (insertSubstEntry) + { + insertSubstAtBottom(declRef, thisSubst); + } + } + return thisSubst; + } + + RefPtr getExprDeclRefType(Expr * expr) + { + if (auto typetype = expr->type->As()) + return typetype->type.As(); + else + return expr->type->As(); + } + + RefPtr ConstructDeclRefExpr( DeclRef declRef, RefPtr baseExpr, @@ -169,84 +218,31 @@ namespace Slang declRefOut = &sexpr->declRef; expr = sexpr; } + + RefPtr baseThisTypeSubst; + if (auto baseDeclRefExpr = baseExpr->As()) + baseThisTypeSubst = getThisTypeSubst(baseDeclRefExpr->declRef, false); + if (auto assocTypeDecl = declRef.As()) { - RefPtr subst = new ThisTypeSubstitution(); - auto baseDeclRefType = baseExpr->type.type.As(); - if (baseDeclRefType && !baseDeclRefType->declRef.getDecl()->As()) - { - // 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()) - subst->sourceType = typeType->type; - expr->type = GetTypeForDeclRef(DeclRef(assocTypeDecl.getDecl(), subst)); - declRefOut->substitutions = subst; + if (!baseThisTypeSubst) + baseThisTypeSubst = new ThisTypeSubstitution(); + expr->type = GetTypeForDeclRef(DeclRef(assocTypeDecl.getDecl(), baseThisTypeSubst)); + + RefPtr outerSubst = getThisTypeSubst(*declRefOut, true); + outerSubst->sourceType = expr->type.type; + if (auto outerTypeType = outerSubst->sourceType.As()) + outerSubst->sourceType = outerTypeType->type; + declRefOut->substitutions = outerSubst; return expr; } - else if (auto constraintDecl = declRef.As()) + + // propagate "this-type" substitutions + if (baseThisTypeSubst) { - expr = baseExpr; if (auto declRefExpr = expr.As()) - declRefOut = &declRefExpr->declRef; - else - return expr; - RefPtr declRefType; - if (auto typeType = baseExpr->type.type.As()) - declRefType = typeType->type->As(); - else - declRefType = baseExpr->type.type.As(); - - if (declRefType) - { - RefPtr subst = new ThisTypeSubstitution(); - subst->sourceType = declRefType; - auto exprType = DeclRefType::Create(getSession(), DeclRef(declRefType->declRef.decl, declRef.substitutions)); - subst->outer = declRef.substitutions; - exprType->declRef.substitutions = subst; - declRefOut->substitutions = subst; - expr->type = exprType; - return expr; - } + insertSubstAtBottom(declRefExpr->declRef, baseThisTypeSubst); } - else if (auto callableDeclRef = declRef.As()) - { - // propagate ThisTypeSubstitution - RefPtr declRefType; - if (auto typeType = baseExpr->type.type.As()) - declRefType = typeType->type->As(); - else - declRefType = baseExpr->type.type.As(); - RefPtr thisSubst; - if (declRefType) - { - auto subst = declRefType->declRef.substitutions; - while (subst) - { - thisSubst = subst.As(); - 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; } @@ -256,6 +252,21 @@ namespace Slang expr->loc = loc; expr->name = declRef.GetName(); expr->type = GetTypeForDeclRef(declRef); + if (auto exprDeclRefType = getExprDeclRefType(expr)) + { + if (auto genParmDecl = exprDeclRefType->declRef.As()) + { + // if this is a reference to generic type param, insert a this-type substitution + auto exprType = GetTypeForDeclRef(declRef); + auto thisSubst = new ThisTypeSubstitution(); + if (auto typetype = exprType.type.As()) + thisSubst->sourceType = typetype->type; + else + thisSubst->sourceType = exprType.type; + thisSubst->outer = declRef.substitutions; + declRef.substitutions = thisSubst; + } + } expr->declRef = declRef; return expr; } @@ -977,33 +988,7 @@ namespace Slang if (auto toDeclRefType = toType->As()) { auto toTypeDeclRef = toDeclRefType->declRef; - if (auto assocDeclRef = toTypeDeclRef.As()) - { - if (auto fromTypeDeclRefType = fromType->As()) - { - if (auto thisSubst = assocDeclRef.substitutions.As()) - { - if (auto fromThisSubst = fromTypeDeclRefType->declRef.substitutions.As()) - { - if (!thisSubst->sourceType || !fromThisSubst->sourceType) - return true; - if (CanCoerce(thisSubst->sourceType.As(), fromThisSubst->sourceType.As(), outCost)) - { - if (outCost) - *outCost = kConversionCost_CastToInterface; - if (outToExpr) - *outToExpr = fromExpr; - return true; - } - } - else - return true; - } - else - return true; - } - } - else if (auto interfaceDeclRef = toTypeDeclRef.As()) + if (auto interfaceDeclRef = toTypeDeclRef.As()) { // Trying to convert to an interface type. // diff --git a/source/slang/slang.natvis b/source/slang/slang.natvis index 357251dcd..31ffa5e80 100644 --- a/source/slang/slang.natvis +++ b/source/slang/slang.natvis @@ -56,4 +56,13 @@ + + {{{mangledName}}} + + mangledName + (*(IRFuncType*)(type.pointer)).resultType + (*(IRFuncType*)(type.pointer)).paramTypes + firstBlock + + \ No newline at end of file diff --git a/source/slang/syntax.cpp b/source/slang/syntax.cpp index 2f3368f4c..24d508ed5 100644 --- a/source/slang/syntax.cpp +++ b/source/slang/syntax.cpp @@ -1213,7 +1213,7 @@ void Type::accept(IValVisitor* visitor, void* extra) } if (!outer) - return !subst->outer; + return !subst->outer || subst->outer.As(); if (!outer->Equals(subst->outer.Ptr())) return false; @@ -1258,19 +1258,9 @@ void Type::accept(IValVisitor* visitor, void* extra) bool ThisTypeSubstitution::Equals(Substitutions* subst) { - // both must be NULL, or non-NULL - if (!this || !subst) - return !this && !subst; - auto thisSubst = dynamic_cast(subst); - if (!thisSubst) - return false; - 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; - return true; + if (subst && dynamic_cast(subst)) + return true; + return false; } -- cgit v1.2.3 From 31e7f84484d227206f3bbb33a8b9be8a9acecfe5 Mon Sep 17 00:00:00 2001 From: Yong He Date: Sat, 4 Nov 2017 15:20:21 -0400 Subject: Passing both assoctype-simple and assoctype-complex test cases. --- source/slang/check.cpp | 84 +++++++--------------- source/slang/emit.cpp | 3 +- source/slang/lookup.cpp | 43 +++++------ source/slang/lower-to-ir.cpp | 4 +- source/slang/slang.vcxproj | 3 + source/slang/slang.vcxproj.filters | 3 + source/slang/syntax.cpp | 84 +++++++++++++++++++++- source/slang/syntax.h | 7 +- tests/compute/assoctype-complex.slang | 9 ++- tests/compute/assoctype-complex.slang.expected.txt | 4 ++ tests/compute/generics-constraint1.slang | 17 ----- .../generics-constructor.slang.expected.txt | 4 ++ 12 files changed, 157 insertions(+), 108 deletions(-) create mode 100644 tests/compute/assoctype-complex.slang.expected.txt delete mode 100644 tests/compute/generics-constraint1.slang create mode 100644 tests/compute/generics-constructor.slang.expected.txt (limited to 'source/slang/check.cpp') diff --git a/source/slang/check.cpp b/source/slang/check.cpp index 5b3247ea4..8e5bab4e5 100644 --- a/source/slang/check.cpp +++ b/source/slang/check.cpp @@ -140,46 +140,6 @@ namespace Slang return result; } - void insertSubstAtBottom(DeclRefBase & declRef, RefPtr substToInsert) - { - RefPtr lastSubst; - auto subst = declRef.substitutions; - while (subst) - { - if (subst) - lastSubst = subst; - subst = subst->outer; - } - if (lastSubst) - lastSubst->outer = substToInsert; - else - declRef.substitutions = substToInsert; - } - - RefPtr getThisTypeSubst(DeclRefBase & declRef, bool insertSubstEntry) - { - RefPtr thisSubst; - auto subst = declRef.substitutions; - while (subst) - { - if (auto s = subst.As()) - { - thisSubst = s; - break; - } - subst = subst->outer; - } - if (!thisSubst) - { - thisSubst = new ThisTypeSubstitution(); - if (insertSubstEntry) - { - insertSubstAtBottom(declRef, thisSubst); - } - } - return thisSubst; - } - RefPtr getExprDeclRefType(Expr * expr) { if (auto typetype = expr->type->As()) @@ -221,19 +181,25 @@ namespace Slang RefPtr baseThisTypeSubst; if (auto baseDeclRefExpr = baseExpr->As()) + { baseThisTypeSubst = getThisTypeSubst(baseDeclRefExpr->declRef, false); - + if (auto baseAssocType = baseDeclRefExpr->declRef.As()) + { + baseThisTypeSubst = new ThisTypeSubstitution(); + baseThisTypeSubst->sourceType = baseDeclRefExpr->type.type; + if (auto typetype = baseThisTypeSubst->sourceType.As()) + baseThisTypeSubst->sourceType = typetype->type; + } + } if (auto assocTypeDecl = declRef.As()) { - if (!baseThisTypeSubst) - baseThisTypeSubst = new ThisTypeSubstitution(); - expr->type = GetTypeForDeclRef(DeclRef(assocTypeDecl.getDecl(), baseThisTypeSubst)); - - RefPtr outerSubst = getThisTypeSubst(*declRefOut, true); - outerSubst->sourceType = expr->type.type; - if (auto outerTypeType = outerSubst->sourceType.As()) - outerSubst->sourceType = outerTypeType->type; - declRefOut->substitutions = outerSubst; + auto newThisTypeSubst = new ThisTypeSubstitution(); + if (baseThisTypeSubst) + newThisTypeSubst->sourceType = baseThisTypeSubst->sourceType; + expr->type = GetTypeForDeclRef(DeclRef(assocTypeDecl.getDecl(), newThisTypeSubst)); + auto declOutThisTypeSubst = getNewThisTypeSubst(*declRefOut); + if (baseThisTypeSubst) + declOutThisTypeSubst->sourceType = baseThisTypeSubst->sourceType; return expr; } @@ -241,7 +207,9 @@ namespace Slang if (baseThisTypeSubst) { if (auto declRefExpr = expr.As()) - insertSubstAtBottom(declRefExpr->declRef, baseThisTypeSubst); + { + getNewThisTypeSubst(declRefExpr->declRef)->sourceType = baseThisTypeSubst->sourceType; + } } expr->type = GetTypeForDeclRef(declRef); return expr; @@ -2000,8 +1968,6 @@ namespace Slang void visitFuncDecl(FuncDecl *functionNode) { - if (functionNode->nameAndLoc.name->text == "test") - printf("break"); if (functionNode->IsChecked(DeclCheckState::Checked)) return; @@ -5861,7 +5827,6 @@ namespace Slang RefPtr CheckInvokeExprWithCheckedOperands(InvokeExpr *expr) { - auto rs = ResolveInvoke(expr); if (auto invoke = dynamic_cast(rs.Ptr())) { @@ -5894,9 +5859,6 @@ namespace Slang RefPtr visitInvokeExpr(InvokeExpr *expr) { - if (auto mbrExpr = expr->FunctionExpr->As()) - if (mbrExpr->name->text == "add") - printf("break"); // check the base expression first expr->FunctionExpr = CheckExpr(expr->FunctionExpr); @@ -6631,9 +6593,11 @@ namespace Slang } else if (auto constraintDeclRef = declRef.As()) { - auto type = DeclRefType::Create(session, constraintDeclRef); - *outTypeResult = type; - return QualType(getTypeType(type)); + // When we access a constraint or an inheritance decl (as a member), + // we are conceptually performing a "cast" to the given super-type, + // with the declaration showing that such a cast is legal. + auto type = GetSup(constraintDeclRef); + return QualType(type); } if( sink ) { diff --git a/source/slang/emit.cpp b/source/slang/emit.cpp index 54788e33a..ccf7f94c0 100644 --- a/source/slang/emit.cpp +++ b/source/slang/emit.cpp @@ -395,8 +395,7 @@ struct EmitVisitor void emitRawTextSpan(char const* textBegin, char const* textEnd) { // TODO(tfoley): Need to make "corelib" not use `int` for pointer-sized things... - auto len = int(textEnd - textBegin); - + auto len = textEnd - textBegin; context->shared->sb.Append(textBegin, len); } diff --git a/source/slang/lookup.cpp b/source/slang/lookup.cpp index a5425074f..b01732362 100644 --- a/source/slang/lookup.cpp +++ b/source/slang/lookup.cpp @@ -410,7 +410,27 @@ void lookUpMemberImpl( if (auto declRefType = type->As()) { auto declRef = declRefType->declRef; - if (auto aggTypeDeclRef = declRef.As()) + if (auto assocTypeDeclRef = declRef.As()) + { + for (auto constraintDeclRef : getMembersOfType(assocTypeDeclRef)) + { + // The super-type in the constraint (e.g., `Foo` in `T : Foo`) + // will tell us a type we should use for lookup. + auto bound = GetSup(constraintDeclRef); + + // Go ahead and use the target type, with an appropriate breadcrumb + // to indicate that we indirected through a type constraint. + + BreadcrumbInfo breadcrumb; + breadcrumb.prev = inBreadcrumbs; + breadcrumb.kind = LookupResultItem::Breadcrumb::Kind::Constraint; + breadcrumb.declRef = constraintDeclRef; + + // TODO: Need to consider case where this might recurse infinitely. + lookUpMemberImpl(session, semantics, name, bound, ioResult, &breadcrumb); + } + } + else if (auto aggTypeDeclRef = declRef.As()) { LookupRequest request; request.semantics = semantics; @@ -452,26 +472,7 @@ void lookUpMemberImpl( lookUpMemberImpl(session, semantics, name, bound, ioResult, &breadcrumb); } } - else if (auto assocTypeDeclRef = declRef.As()) - { - for (auto constraintDeclRef : getMembersOfType(assocTypeDeclRef)) - { - // The super-type in the constraint (e.g., `Foo` in `T : Foo`) - // will tell us a type we should use for lookup. - auto bound = GetSup(constraintDeclRef); - - // Go ahead and use the target type, with an appropriate breadcrumb - // to indicate that we indirected through a type constraint. - - BreadcrumbInfo breadcrumb; - breadcrumb.prev = inBreadcrumbs; - breadcrumb.kind = LookupResultItem::Breadcrumb::Kind::Constraint; - breadcrumb.declRef = constraintDeclRef; - - // TODO: Need to consider case where this might recurse infinitely. - lookUpMemberImpl(session, semantics, name, bound, ioResult, &breadcrumb); - } - } + } } diff --git a/source/slang/lower-to-ir.cpp b/source/slang/lower-to-ir.cpp index 7a3e9356a..81fab7108 100644 --- a/source/slang/lower-to-ir.cpp +++ b/source/slang/lower-to-ir.cpp @@ -2652,8 +2652,6 @@ struct DeclLoweringVisitor : DeclVisitor 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); @@ -3086,7 +3084,7 @@ LoweredValInfo emitDeclRef( // If this declaration reference doesn't involve any specializations, // then we are done at this point. - if(!declRef.substitutions) + if(!hasGenericSubstitutions(declRef.substitutions)) return loweredDecl; auto val = getSimpleVal(context, loweredDecl); diff --git a/source/slang/slang.vcxproj b/source/slang/slang.vcxproj index b09eae3ab..15fde5673 100644 --- a/source/slang/slang.vcxproj +++ b/source/slang/slang.vcxproj @@ -296,6 +296,9 @@ $(OutDir)slang-generate.exe + + + diff --git a/source/slang/slang.vcxproj.filters b/source/slang/slang.vcxproj.filters index ef9b3c8e5..011199af4 100644 --- a/source/slang/slang.vcxproj.filters +++ b/source/slang/slang.vcxproj.filters @@ -77,4 +77,7 @@ + + + \ No newline at end of file diff --git a/source/slang/syntax.cpp b/source/slang/syntax.cpp index 24d508ed5..161f9cc26 100644 --- a/source/slang/syntax.cpp +++ b/source/slang/syntax.cpp @@ -530,7 +530,14 @@ void Type::accept(IValVisitor* visitor, void* extra) // we want to replace it with the actual associated type else if (auto assocTypeDecl = dynamic_cast(declRef.getDecl())) { + auto thisSubst = getThisTypeSubst(declRef, false); + auto oldSubstSrc = thisSubst ? thisSubst->sourceType : nullptr; + bool restore = false; + if (thisSubst && thisSubst->sourceType.Ptr() == dynamic_cast(this)) + thisSubst->sourceType = nullptr; auto newSubst = declRef.substitutions->SubstituteImpl(subst, ioDiff); + if (restore) + thisSubst->sourceType = oldSubstSrc; if (auto thisTypeSubst = newSubst.As()) { if (thisTypeSubst->sourceType) @@ -1258,6 +1265,8 @@ void Type::accept(IValVisitor* visitor, void* extra) bool ThisTypeSubstitution::Equals(Substitutions* subst) { + if (!subst) + return true; if (subst && dynamic_cast(subst)) return true; return false; @@ -1323,7 +1332,7 @@ void Type::accept(IValVisitor* visitor, void* extra) if (decl != declRef.decl) return false; if (!substitutions) - return !declRef.substitutions; + return !declRef.substitutions || declRef.substitutions.As(); if (!substitutions->Equals(declRef.substitutions.Ptr())) return false; @@ -1634,4 +1643,77 @@ void Type::accept(IValVisitor* visitor, void* extra) + void insertSubstAtTop(DeclRefBase & declRef, RefPtr substToInsert) + { + substToInsert->outer = declRef.substitutions; + declRef.substitutions = substToInsert; + } + + RefPtr getThisTypeSubst(DeclRefBase & declRef, bool insertSubstEntry) + { + RefPtr thisSubst; + auto subst = declRef.substitutions; + while (subst) + { + if (auto s = subst.As()) + { + thisSubst = s; + break; + } + subst = subst->outer; + } + if (!thisSubst) + { + thisSubst = new ThisTypeSubstitution(); + if (insertSubstEntry) + { + insertSubstAtTop(declRef, thisSubst); + } + } + return thisSubst; + } + + RefPtr getNewThisTypeSubst(DeclRefBase & declRef) + { + auto oldSubst = getThisTypeSubst(declRef, false); + if (oldSubst) + removeSubstitution(declRef, oldSubst); + return getThisTypeSubst(declRef, true); + } + + void removeSubstitution(DeclRefBase & declRef, RefPtr toRemove) + { + if (!declRef.substitutions) + return; + if (toRemove == declRef.substitutions) + { + declRef.substitutions = declRef.substitutions->outer; + return; + } + auto prev = declRef.substitutions; + auto subst = prev->outer; + while (subst) + { + if (subst == toRemove) + { + prev->outer = subst->outer; + break; + } + prev = subst; + subst = subst->outer; + } + } + + bool hasGenericSubstitutions(RefPtr subst) + { + auto p = subst.Ptr(); + while (p) + { + if (dynamic_cast(p)) + return true; + p = p->outer.Ptr(); + } + return false; + } + } diff --git a/source/slang/syntax.h b/source/slang/syntax.h index cf75b5624..bda43b336 100644 --- a/source/slang/syntax.h +++ b/source/slang/syntax.h @@ -1155,7 +1155,12 @@ namespace Slang RefPtr createDefaultSubstitutions( Session* session, Decl* decl); - + + RefPtr getNewThisTypeSubst(DeclRefBase & declRef); + RefPtr getThisTypeSubst(DeclRefBase & declRef, bool insertSubstEntry); + void removeSubstitution(DeclRefBase & declRef, RefPtr subst); + bool hasGenericSubstitutions(RefPtr subst); + } // namespace Slang #endif \ No newline at end of file diff --git a/tests/compute/assoctype-complex.slang b/tests/compute/assoctype-complex.slang index f29d231b6..16d6b1514 100644 --- a/tests/compute/assoctype-complex.slang +++ b/tests/compute/assoctype-complex.slang @@ -1,7 +1,7 @@ //TEST(smoke, compute):COMPARE_COMPUTE:-xslang -use-ir //TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out -RWStructuredBuffer outputBuffer; +RWStructuredBuffer outputBuffer; interface IBase { associatedtype V; @@ -16,9 +16,10 @@ interface ISimple struct Val : IBase { typedef int V; + int base; V sub(V a0, V a1) { - return a0-a1; + return a0 - a1 + base; } }; @@ -42,6 +43,8 @@ void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID) { Simple s; Val v0, v1; - float outVal = test(s, v0, v1); // == 1.0 + v0.base = 1; + v1.base = 2; + int outVal = test(s, v0, v1); // == 4.0 outputBuffer[dispatchThreadID.x] = outVal; } \ No newline at end of file diff --git a/tests/compute/assoctype-complex.slang.expected.txt b/tests/compute/assoctype-complex.slang.expected.txt new file mode 100644 index 000000000..e43ad329a --- /dev/null +++ b/tests/compute/assoctype-complex.slang.expected.txt @@ -0,0 +1,4 @@ +4 +4 +4 +4 \ No newline at end of file diff --git a/tests/compute/generics-constraint1.slang b/tests/compute/generics-constraint1.slang deleted file mode 100644 index aa8d398e8..000000000 --- a/tests/compute/generics-constraint1.slang +++ /dev/null @@ -1,17 +0,0 @@ -//TEST(smoke, compute):COMPARE_COMPUTE:-xslang -use-ir -//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out - -RWStructuredBuffer outputBuffer; - -__generic -T test(T v0, T v1) -{ - return v0; -} - -[numthreads(4, 1, 1)] -void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID) -{ - float outVal = test(1.0, 2.0); - outputBuffer[dispatchThreadID.x] = outVal; -} \ No newline at end of file diff --git a/tests/compute/generics-constructor.slang.expected.txt b/tests/compute/generics-constructor.slang.expected.txt new file mode 100644 index 000000000..e54af3bc8 --- /dev/null +++ b/tests/compute/generics-constructor.slang.expected.txt @@ -0,0 +1,4 @@ +40400000 +40400000 +40400000 +40400000 -- cgit v1.2.3 From 8c0a429c292ea6735ce1ac14c22125266e8fb6c5 Mon Sep 17 00:00:00 2001 From: Yong He Date: Sat, 4 Nov 2017 18:45:42 -0400 Subject: fix warnings --- source/slang/check.cpp | 4 ++-- source/slang/emit.cpp | 2 +- source/slang/lower-to-ir.cpp | 2 +- source/slang/lower.cpp | 2 +- source/slang/syntax.cpp | 4 ++-- 5 files changed, 7 insertions(+), 7 deletions(-) (limited to 'source/slang/check.cpp') diff --git a/source/slang/check.cpp b/source/slang/check.cpp index d01c913b1..58c1762bb 100644 --- a/source/slang/check.cpp +++ b/source/slang/check.cpp @@ -1661,7 +1661,7 @@ namespace Slang if (!declRefType) return false; - auto subStructTypeDecl = declRefType->declRef.getDecl()->As(); + auto structTypeDecl = declRefType->declRef.getDecl()->As(); //TODO: What do we do if type is a generic specialization? // i.e. if the struct defines typedef Generic T; // how to check if T satisfies the associatedtype constraints? @@ -1669,7 +1669,7 @@ namespace Slang bool conformance = true; for (auto & inheritanceDecl : constraintList) { - conformance = conformance && checkConformance(subStructTypeDecl, inheritanceDecl.Ptr()); + conformance = conformance && checkConformance(structTypeDecl, inheritanceDecl.Ptr()); } return conformance; } diff --git a/source/slang/emit.cpp b/source/slang/emit.cpp index 849ca7e66..fc6fc0184 100644 --- a/source/slang/emit.cpp +++ b/source/slang/emit.cpp @@ -1194,7 +1194,7 @@ struct EmitVisitor EmitDeclarator(declarator); } - void visitThisType(ThisType* type, TypeEmitArg const&) + void visitThisType(ThisType* /*type*/, TypeEmitArg const&) { return; } diff --git a/source/slang/lower-to-ir.cpp b/source/slang/lower-to-ir.cpp index 4595a0319..e149036a7 100644 --- a/source/slang/lower-to-ir.cpp +++ b/source/slang/lower-to-ir.cpp @@ -882,7 +882,7 @@ struct ValLoweringVisitor : ValVisitor ThisType::SubstituteImpl(Substitutions* subst, int* ioDiff) + RefPtr ThisType::SubstituteImpl(Substitutions* subst, int* /*ioDiff*/) { while (subst) { -- cgit v1.2.3 From 6e4ba9bd552923b08cd56b4542b2f29e8df8ca0c Mon Sep 17 00:00:00 2001 From: Yong He Date: Sat, 4 Nov 2017 20:07:47 -0400 Subject: naming cleanup --- source/slang/check.cpp | 4 ++-- source/slang/slang.vcxproj | 3 --- source/slang/slang.vcxproj.filters | 3 --- 3 files changed, 2 insertions(+), 8 deletions(-) (limited to 'source/slang/check.cpp') diff --git a/source/slang/check.cpp b/source/slang/check.cpp index 58c1762bb..bc3823292 100644 --- a/source/slang/check.cpp +++ b/source/slang/check.cpp @@ -1638,10 +1638,10 @@ namespace Slang { // this is a sub type (e.g. nested struct declaration) in an aggregate type // check if this sub type declaration satisfies the constraints defined by the associated type - if (auto requiredTypeDecl = requiredMemberDeclRef.As()) + if (auto requiredTypeDeclRef = requiredMemberDeclRef.As()) { bool conformance = true; - for (auto & inheritanceDecl : requiredTypeDecl.getDecl()->getMembersOfType()) + for (auto & inheritanceDecl : requiredTypeDeclRef.getDecl()->getMembersOfType()) { conformance = conformance && checkConformance(subStructTypeDecl, inheritanceDecl.Ptr()); } diff --git a/source/slang/slang.vcxproj b/source/slang/slang.vcxproj index 15fde5673..b09eae3ab 100644 --- a/source/slang/slang.vcxproj +++ b/source/slang/slang.vcxproj @@ -296,9 +296,6 @@ $(OutDir)slang-generate.exe - - - diff --git a/source/slang/slang.vcxproj.filters b/source/slang/slang.vcxproj.filters index 011199af4..ef9b3c8e5 100644 --- a/source/slang/slang.vcxproj.filters +++ b/source/slang/slang.vcxproj.filters @@ -77,7 +77,4 @@ - - - \ No newline at end of file -- cgit v1.2.3 From 0d250f0d49e9e29d143c5794671669ea025b357e Mon Sep 17 00:00:00 2001 From: Yong He Date: Sat, 4 Nov 2017 20:21:19 -0400 Subject: style fixes --- source/slang/check.cpp | 3 ++- source/slang/parser.cpp | 17 ++++++++++------- 2 files changed, 12 insertions(+), 8 deletions(-) (limited to 'source/slang/check.cpp') diff --git a/source/slang/check.cpp b/source/slang/check.cpp index bc3823292..79a4f28cf 100644 --- a/source/slang/check.cpp +++ b/source/slang/check.cpp @@ -1972,8 +1972,9 @@ namespace Slang return; VisitFunctionDeclaration(functionNode); - // TODO: This should really onlye set "checked header" + // TODO: This should really only set "checked header" functionNode->SetCheckState(DeclCheckState::Checked); + // TODO: should put the checking of the body onto a "work list" // to avoid recursion here. if (functionNode->Body) diff --git a/source/slang/parser.cpp b/source/slang/parser.cpp index 954496b68..57956485a 100644 --- a/source/slang/parser.cpp +++ b/source/slang/parser.cpp @@ -1428,8 +1428,7 @@ namespace Slang return typeExpr; } - static TypeSpec - parseTypeSpec(Parser* parser) + static TypeSpec parseTypeSpec(Parser* parser) { TypeSpec typeSpec; @@ -1462,15 +1461,19 @@ namespace Slang RefPtr typeExpr = basicType; - while (parser->LookAheadToken(TokenType::OpLess) || parser->LookAheadToken(TokenType::Dot)) + bool shouldLoop = true; + while (shouldLoop) { - if (parser->LookAheadToken(TokenType::OpLess)) + switch (peekTokenType(parser)) { + case TokenType::OpLess: typeExpr = parseGenericApp(parser, typeExpr); - } - else - { + break; + case TokenType::Dot: typeExpr = parseMemberType(parser, typeExpr); + break; + default: + shouldLoop = false; } } -- cgit v1.2.3 From ff7c46a11787ca6ecebf0a224772a41efef33fc0 Mon Sep 17 00:00:00 2001 From: Yong He Date: Sun, 5 Nov 2017 05:49:42 -0500 Subject: small cleanups --- source/slang/check.cpp | 2 ++ source/slang/ir.cpp | 4 +++- source/slang/lower-to-ir.cpp | 7 +++++-- 3 files changed, 10 insertions(+), 3 deletions(-) (limited to 'source/slang/check.cpp') diff --git a/source/slang/check.cpp b/source/slang/check.cpp index 79a4f28cf..ed2ed4a1b 100644 --- a/source/slang/check.cpp +++ b/source/slang/check.cpp @@ -1662,6 +1662,8 @@ namespace Slang return false; auto structTypeDecl = declRefType->declRef.getDecl()->As(); + if (!structTypeDecl) + return false; //TODO: What do we do if type is a generic specialization? // i.e. if the struct defines typedef Generic T; // how to check if T satisfies the associatedtype constraints? diff --git a/source/slang/ir.cpp b/source/slang/ir.cpp index 04569771a..ab961a159 100644 --- a/source/slang/ir.cpp +++ b/source/slang/ir.cpp @@ -562,11 +562,13 @@ namespace Slang IRValue * IRBuilder::getTypeVal(IRType * type) { - auto irValue = createValue( + auto irValue = createValue( this, kIROp_TypeType, nullptr); irValue->type = type; + if (auto typetype = dynamic_cast(type)) + irValue->type = typetype->type; return irValue; } diff --git a/source/slang/lower-to-ir.cpp b/source/slang/lower-to-ir.cpp index be91b9d3d..2672c5698 100644 --- a/source/slang/lower-to-ir.cpp +++ b/source/slang/lower-to-ir.cpp @@ -2311,8 +2311,11 @@ struct DeclLoweringVisitor : DeclVisitor ensureDecl(context, inheritanceDecl); } - // For now, we don't have an IR-level representation - // for the type itself. + // TODO: we currently store a Decl* in the witness table, which causes this function + // being invoked to translate the witness table entry into an IRValue. + // We should really allow a witness table entry to represent a type and not having to + // construct the type here. The current implementation will not work when the struct type + // is defined in a generic parent (we lose the environmental substitutions). return LoweredValInfo::simple(context->irBuilder->getTypeVal(DeclRefType::Create(context->getSession(), DeclRef(decl, nullptr)))); } -- cgit v1.2.3