From 6e591ada0eb652c320bba4bd8a46cd579946df01 Mon Sep 17 00:00:00 2001 From: Yong He Date: Tue, 7 Nov 2017 19:09:40 -0500 Subject: Support generic interface methods (#251) * improve diagnostic messages and prevent fatal errors from crashing the compiler. * fix top level exception catching. * spelling fix * change wording of invalidSwizzleExpr diagnostic * add speculative GenericsApp expr parsing * add new test case of cascading generics call. * Fixing bugs in compiling cascaded generic function calls. Add implementation of DeclaredSubTypeWitness::SubstituteImpl() This is not needed by the type checker, but needed by IR specialization. When input source contains cascading generic function call, the arguments to `specialize` instruction is currently represented as a substitution. The arg values of this subsittution can be a `DeclaredSubTypeWitness` when a generic function uses one of its generic parameter to specialize another generic function. When the top level generics function is being specialized, this substitution argument, which is a `DeclaredSubTypeWitness`, needs to be substituted with the witness that used to specialize the top level function in the specialized specialize instruction as well. * add a test case for cascading generic function call. * parser bug fix * fixes #255 * add test case for issue #255 * Generate missing `specialize` instruction when calling a generic method from an interface constraint. When calling a generic method via an interface, we should be generating the following ir: ... f = lookup_interface_method(...) f_s = specailize(f, declRef) ... This commit fixes this `emitFuncRef` function to emit the needed `specialize` instruction. * fixes #260 This fix follows the second apporach in the disucssion. It generated mangled name for specialized functions by appending new substitution type names to the original mangled name. * Disabling removing and re-inserting specailized functions in getSpecalizeFunc() I am not sure why it is needed, it seems HLSL and GLSL backends are generating forward declarations anyways, so the order of functions in IRModule shouldn't matter. * cleanup and complete test cases. * fix warnings --- source/slang/ir.cpp | 36 ++++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) (limited to 'source/slang/ir.cpp') diff --git a/source/slang/ir.cpp b/source/slang/ir.cpp index 439bc7797..b1af6521c 100644 --- a/source/slang/ir.cpp +++ b/source/slang/ir.cpp @@ -55,15 +55,15 @@ namespace Slang } } - void IRUse::set(IRValue* usedValue) + void IRUse::set(IRValue* usedVal) { // clear out the old value - if (usedValue) + if (usedVal) { *prevLink = nextUse; } - init(user, usedValue); + init(user, usedVal); } void IRUse::clear() @@ -3750,8 +3750,6 @@ namespace Slang { if( auto subtypeWitness = dynamic_cast(val) ) { - // We need to look up the IR value that represents the - // given subtype witness. String mangledName = getMangledNameForConformanceWitness( subtypeWitness->sub, subtypeWitness->sup); @@ -3948,8 +3946,11 @@ namespace Slang // has already been made. To do that we will need to // compute the mangled name of the specialized function, // so that we can look for existing declarations. - - String specMangledName = getMangledName(specDeclRef); + String specMangledName; + if (genericFunc->genericDecl == specDeclRef.decl) + specMangledName = getMangledName(specDeclRef); + else + specMangledName = mangleSpecializedFuncName(genericFunc->mangledName, specDeclRef.substitutions); // TODO: This is a terrible linear search, and we should // avoid it by building a dictionary ahead of time, @@ -3992,8 +3993,8 @@ namespace Slang // // TODO: This shouldn't be needed, if we introduce a sorting // step before we emit code. - specFunc->removeFromParent(); - specFunc->insertAfter(genericFunc); + //specFunc->removeFromParent(); + //specFunc->insertAfter(genericFunc); // At this point we've created a new non-generic function, // which means we should add it to our work list for @@ -4026,8 +4027,20 @@ namespace Slang auto keyDeclRef = ((IRDeclRef*) requirementKey)->declRef; // If the keys don't match, continue with the next entry. - if(!keyDeclRef.Equals(requirementDeclRef)) - continue; + if (!keyDeclRef.Equals(requirementDeclRef)) + { + // requirementDeclRef may be pointing to the inner decl of a generic decl + // in this case we compare keyDeclRef against the parent decl of requiredDeclRef + if (auto genRequiredDeclRef = requirementDeclRef.GetParent().As()) + { + if (!keyDeclRef.Equals(genRequiredDeclRef)) + { + continue; + } + } + else + continue; + } // If the keys matched, then we use the value from // this entry. @@ -4178,7 +4191,6 @@ namespace Slang // Use the witness table to look up the value that // satisfies the requirement. auto satisfyingVal = findWitnessVal(witnessTable, requirementDeclRef); - // We expect to always find something, but lets just // be careful here. if(!satisfyingVal) -- cgit v1.2.3