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/lower.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'source/slang/lower.cpp') diff --git a/source/slang/lower.cpp b/source/slang/lower.cpp index 0f16a8ad7..776a55530 100644 --- a/source/slang/lower.cpp +++ b/source/slang/lower.cpp @@ -765,6 +765,7 @@ struct LoweringVisitor loweredDeclRef.As()); } + RefPtr visitNamedExpressionType(NamedExpressionType* type) { if (shared->target == CodeGenTarget::GLSL) @@ -778,6 +779,13 @@ struct LoweringVisitor translateDeclRef(DeclRef(type->declRef)).As()); } + RefPtr visitAssocTypeDeclRefType(AssocTypeDeclRefType* type) + { + // not supported by lowering + SLANG_UNREACHABLE("visitAssocTypeDeclRefType in LowerVisitor"); + return nullptr; + } + RefPtr visitTypeType(TypeType* type) { return getTypeType(lowerType(type->type)); @@ -2820,6 +2828,13 @@ struct LoweringVisitor return LoweredDecl(); } + LoweredDecl visitAssocTypeDecl(AssocTypeDecl * /*assocType*/) + { + // not supported + SLANG_UNREACHABLE("visitAssocTypeDecl in LowerVisitor"); + return LoweredDecl(); + } + LoweredDecl visitTypeDefDecl(TypeDefDecl* decl) { if (shared->target == CodeGenTarget::GLSL) -- 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/lower.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 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/lower.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/lower.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 cb0a5773cd3b3564c4a19b85aaddd3d9cc63a3c7 Mon Sep 17 00:00:00 2001 From: Yong He Date: Sat, 4 Nov 2017 16:54:44 -0400 Subject: bug fix --- source/slang/lower.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source/slang/lower.cpp') diff --git a/source/slang/lower.cpp b/source/slang/lower.cpp index bdd041f71..7f18659ae 100644 --- a/source/slang/lower.cpp +++ b/source/slang/lower.cpp @@ -2572,7 +2572,8 @@ struct LoweringVisitor else if (auto thisSubst = dynamic_cast(inSubstitutions)) { RefPtr result = new ThisTypeSubstitution(); - result->sourceType = translateVal(result->sourceType); + if (result->sourceType) + result->sourceType = translateVal(result->sourceType); return result; } return nullptr; -- cgit v1.2.3 From 00e03825d80c4997fa35461d82ff267f721ae8a6 Mon Sep 17 00:00:00 2001 From: Yong He Date: Sat, 4 Nov 2017 18:07:26 -0400 Subject: merge --- source/slang/lower.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source/slang/lower.cpp') diff --git a/source/slang/lower.cpp b/source/slang/lower.cpp index d207aac72..a9daa6eba 100644 --- a/source/slang/lower.cpp +++ b/source/slang/lower.cpp @@ -3835,10 +3835,10 @@ struct LoweringVisitor "Vector").As(); auto vectorTypeDecl = vectorGenericDecl->inner; - auto substitutions = new GenericSubstitution(); - substitutions->genericDecl = vectorGenericDecl.Ptr(); - substitutions->args.Add(elementType); - substitutions->args.Add(elementCount); + auto substs = new GenericSubstitution(); + substs->genericDecl = vectorGenericDecl.Ptr(); + substs->args.Add(elementType); + substs->args.Add(elementCount); auto declRef = DeclRef(vectorTypeDecl.Ptr(), substs); -- 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/lower.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 33d9f07d6c86e80c44af4de0693532cee6635135 Mon Sep 17 00:00:00 2001 From: Yong He Date: Sat, 4 Nov 2017 19:19:23 -0400 Subject: cleanup useless code --- source/slang/emit.cpp | 5 --- source/slang/lower-to-ir.cpp | 5 --- source/slang/lower.cpp | 5 --- source/slang/parser.cpp | 2 +- source/slang/syntax.cpp | 79 -------------------------------------------- source/slang/type-defs.h | 32 ------------------ 6 files changed, 1 insertion(+), 127 deletions(-) (limited to 'source/slang/lower.cpp') diff --git a/source/slang/emit.cpp b/source/slang/emit.cpp index fc6fc0184..056454845 100644 --- a/source/slang/emit.cpp +++ b/source/slang/emit.cpp @@ -1194,11 +1194,6 @@ 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 a7baf265c..be91b9d3d 100644 --- a/source/slang/lower-to-ir.cpp +++ b/source/slang/lower-to-ir.cpp @@ -882,11 +882,6 @@ struct ValLoweringVisitor : ValVisitor()); } - RefPtr visitThisType(ThisType* type) - { - return type; - } - RefPtr visitNamedExpressionType(NamedExpressionType* type) { if (shared->target == CodeGenTarget::GLSL) diff --git a/source/slang/parser.cpp b/source/slang/parser.cpp index 8e0d5d66f..954496b68 100644 --- a/source/slang/parser.cpp +++ b/source/slang/parser.cpp @@ -2087,7 +2087,7 @@ namespace Slang return decl; } - static void parseOptionalInheritanceClause(Parser* parser, ContainerDecl* decl) + static void parseOptionalInheritanceClause(Parser* parser, AggTypeDecl* decl) { if( AdvanceIf(parser, TokenType::Colon) ) { diff --git a/source/slang/syntax.cpp b/source/slang/syntax.cpp index 255cf4ff1..9acdadad6 100644 --- a/source/slang/syntax.cpp +++ b/source/slang/syntax.cpp @@ -376,85 +376,6 @@ 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() diff --git a/source/slang/type-defs.h b/source/slang/type-defs.h index 7eda5b5ce..60f519c82 100644 --- a/source/slang/type-defs.h +++ b/source/slang/type-defs.h @@ -55,38 +55,6 @@ 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