diff options
| author | Yong He <yonghe@outlook.com> | 2018-01-21 07:09:55 -0500 |
|---|---|---|
| committer | Yong He <yonghe@outlook.com> | 2018-01-21 07:09:55 -0500 |
| commit | ce879112cb16e3def1b8673104e7123b8b17ee2a (patch) | |
| tree | 9b2a63c4c2c6256d33cb32b925ed9820cf13071d /source | |
| parent | 913f4d09b91e3fd7449468b135881c940cacb3c0 (diff) | |
Improvements and bug fixes for global type parameters
1. allow spReflection_FindTypeByName to accept arbitrary type expression string
2. allow const int generic value to be used as expression value, and as array size
3. various bug fixes in witness table specialization / function cloning during specializeIRForEntryPoint to avoid creating duplicate global values, not copying the right definition of a function from the other module, not cloning witness tables that are required by specializeGenerics etc.
Diffstat (limited to 'source')
| -rw-r--r-- | source/slang/check.cpp | 29 | ||||
| -rw-r--r-- | source/slang/compiler.h | 2 | ||||
| -rw-r--r-- | source/slang/emit.cpp | 2 | ||||
| -rw-r--r-- | source/slang/ir-insts.h | 3 | ||||
| -rw-r--r-- | source/slang/ir.cpp | 193 | ||||
| -rw-r--r-- | source/slang/legalize-types.cpp | 2 | ||||
| -rw-r--r-- | source/slang/lower-to-ir.cpp | 49 | ||||
| -rw-r--r-- | source/slang/reflection.cpp | 16 | ||||
| -rw-r--r-- | source/slang/slang.cpp | 29 | ||||
| -rw-r--r-- | source/slang/syntax.cpp | 4 |
10 files changed, 240 insertions, 89 deletions
diff --git a/source/slang/check.cpp b/source/slang/check.cpp index c4aa9bfba..52558ee15 100644 --- a/source/slang/check.cpp +++ b/source/slang/check.cpp @@ -6849,6 +6849,23 @@ namespace Slang return (!decl->primaryDecl) || (decl == decl->primaryDecl); } + RefPtr<Type> checkProperType(TranslationUnitRequest * tu, TypeExp typeExp) + { + RefPtr<Type> type; + DiagnosticSink nSink; + nSink.sourceManager = tu->compileRequest->sourceManager; + SemanticsVisitor visitor( + &nSink, + tu->compileRequest, + tu); + auto typeOut = visitor.CheckProperType(typeExp); + if (!nSink.errorCount) + { + type = typeOut.type; + } + return type; + } + void validateEntryPoint( EntryPointRequest* entryPoint) { @@ -6956,15 +6973,9 @@ namespace Slang { RefPtr<Expr> typeExpr = entryPoint->compileRequest->parseTypeString(entryPoint->getTranslationUnit(), name, s); - DiagnosticSink nSink; - SemanticsVisitor visitor( - &nSink, - translationUnit->compileRequest, - translationUnit); - auto typeOut = visitor.CheckProperType(TypeExp(typeExpr)); - if (!nSink.errorCount) - { - type = typeOut.type; + type = checkProperType(translationUnit, TypeExp(typeExpr)); + if (type) + { break; } } diff --git a/source/slang/compiler.h b/source/slang/compiler.h index 4854f4060..960e67ffe 100644 --- a/source/slang/compiler.h +++ b/source/slang/compiler.h @@ -319,6 +319,8 @@ namespace Slang ~CompileRequest(); RefPtr<Expr> parseTypeString(TranslationUnitRequest * translationUnit, String typeStr, RefPtr<Scope> scope); + + Type* getTypeFromString(String typeStr); void parseTranslationUnit( TranslationUnitRequest* translationUnit); diff --git a/source/slang/emit.cpp b/source/slang/emit.cpp index 53f02cc56..18216de81 100644 --- a/source/slang/emit.cpp +++ b/source/slang/emit.cpp @@ -7500,7 +7500,7 @@ String emitEntryPoint( // none of our target supports generics, or interfaces, // so we need to specialize those away. // - specializeGenerics(irModule); + specializeGenerics(irModule, sharedContext.target); // Debugging code for IR transformations... #if 0 diff --git a/source/slang/ir-insts.h b/source/slang/ir-insts.h index 23e948b3a..dedc906d0 100644 --- a/source/slang/ir-insts.h +++ b/source/slang/ir-insts.h @@ -641,7 +641,8 @@ void specializeIRForEntryPoint( // Find suitable uses of the `specialize` instruction that // can be replaced with references to specialized functions. void specializeGenerics( - IRModule* module); + IRModule* module, + CodeGenTarget target); // diff --git a/source/slang/ir.cpp b/source/slang/ir.cpp index 994ac82ff..7318bff4c 100644 --- a/source/slang/ir.cpp +++ b/source/slang/ir.cpp @@ -7,6 +7,13 @@ namespace Slang { + struct IRSpecContext; + + IRGlobalValue* cloneGlobalValueWithMangledName( + IRSpecContext* context, + String const& mangledName, + IRGlobalValue* originalVal); + static const IROpInfo kIROpInfos[] = { @@ -3065,6 +3072,9 @@ namespace Slang struct IRSharedSpecContext { + // The code-generation target in use + CodeGenTarget target; + // The specialized module we are building IRModule* module; @@ -3091,6 +3101,10 @@ namespace Slang struct IRSpecContextBase { + // A map from the mangled name of a global variable + // to the layout to use for it. + Dictionary<String, VarLayout*> globalVarLayouts; + IRSharedSpecContext* shared; IRSharedSpecContext* getShared() { return shared; } @@ -3224,13 +3238,6 @@ namespace Slang struct IRSpecContext : IRSpecContextBase { - // The code-generation target in use - CodeGenTarget target; - - // A map from the mangled name of a global variable - // to the layout to use for it. - Dictionary<String, VarLayout*> globalVarLayouts; - // Override the "maybe clone" logic so that we always clone virtual IRValue* maybeCloneValue(IRValue* originalVal) override; @@ -3434,18 +3441,31 @@ namespace Slang return newDeclRef; } - IRValue* cloneValue( IRSpecContextBase* context, IRValue* originalValue) { IRValue* clonedValue = nullptr; if (context->getClonedValues().TryGetValue(originalValue, clonedValue)) + { return clonedValue; + } return context->maybeCloneValue(originalValue); } + IRValue* maybeCloneValueWithMangledName( + IRSpecContextBase* context, + IRGlobalValue* originalValue) + { + for (auto gv = context->shared->module->firstGlobalValue; gv; gv = gv->nextGlobalValue) + { + if (gv->mangledName == originalValue->mangledName) + return gv; + } + return cloneValue(context, originalValue); + } + void cloneInst( IRSpecContextBase* context, IRBuilder* builder, @@ -3468,18 +3488,23 @@ namespace Slang context->maybeCloneType(originalInst->type), 0, nullptr, argCount, nullptr); - builder->addInst(clonedInst); registerClonedValue(context, clonedInst, originalInst); - - cloneDecorations(context, clonedInst, originalInst); - + auto oldBuilder = context->builder; + context->builder = builder; for (UInt aa = 0; aa < argCount; ++aa) { IRValue* originalArg = originalInst->getArg(aa); - IRValue* clonedArg = cloneValue(context, originalArg); - + IRValue* clonedArg; + if (originalArg->op == kIROp_witness_table) + clonedArg = cloneGlobalValueWithMangledName((IRSpecContext*)context, + ((IRGlobalValue*)originalArg)->mangledName, (IRGlobalValue*)originalArg); + else + clonedArg = cloneValue(context, originalArg); clonedInst->getArgs()[aa].init(clonedInst, clonedArg); } + builder->addInst(clonedInst); + context->builder = oldBuilder; + cloneDecorations(context, clonedInst, originalInst); } break; @@ -3524,12 +3549,15 @@ namespace Slang IRSpecContextBase* context, IRWitnessTable* originalTable, IROriginalValuesForClone const& originalValues, - IRWitnessTable* dstTable = nullptr) + IRWitnessTable* dstTable = nullptr, + bool registerValue = true) { auto clonedTable = dstTable ? dstTable : context->builder->createWitnessTable(); - registerClonedValue(context, clonedTable, originalValues); + if (registerValue) + registerClonedValue(context, clonedTable, originalValues); auto mangledName = originalTable->mangledName; + clonedTable->mangledName = mangledName; clonedTable->genericDecl = originalTable->genericDecl; clonedTable->subTypeDeclRef = originalTable->subTypeDeclRef; @@ -3539,8 +3567,11 @@ namespace Slang // Clone the entries in the witness table as well for( auto originalEntry : originalTable->entries ) { - auto clonedKey = context->maybeCloneValue(originalEntry->requirementKey.usedValue); - auto clonedVal = context->maybeCloneValue(originalEntry->satisfyingVal.usedValue); + auto clonedKey = cloneValue(context, originalEntry->requirementKey.usedValue); + + // if a global val with the mangled name already exists, don't clone again + auto clonedVal = maybeCloneValueWithMangledName(context, (IRGlobalValue*)(originalEntry->satisfyingVal.usedValue)); + /*auto clonedEntry = */context->builder->createWitnessTableEntry( clonedTable, clonedKey, @@ -3555,7 +3586,7 @@ namespace Slang IRWitnessTable* originalTable, IRWitnessTable* dstTable = nullptr) { - return cloneWitnessTableImpl(context, originalTable, IROriginalValuesForClone(), dstTable); + return cloneWitnessTableImpl(context, originalTable, IROriginalValuesForClone(), dstTable, false); } void cloneGlobalValueWithCodeCommon( @@ -3690,14 +3721,6 @@ namespace Slang // and their instructions. cloneFunctionCommon(context, clonedFunc, originalFunc); - // for now, clone all unreferenced witness tables - for (auto gv = context->getOriginalModule()->getFirstGlobalValue(); - gv; gv = gv->getNextValue()) - { - if (gv->op == kIROp_witness_table) - cloneGlobalValue(context, (IRWitnessTable*)gv); - } - // We need to attach the layout information for // the entry point to this declaration, so that // we can use it to inform downstream code emit. @@ -3746,7 +3769,7 @@ namespace Slang // TODO: We shouldn't be using strings for this. String getTargetName(IRSpecContext* context) { - switch( context->target ) + switch( context->shared->target ) { case CodeGenTarget::HLSL: return "hlsl"; @@ -4035,7 +4058,8 @@ namespace Slang IRSharedSpecContext* sharedContext, Session* session, IRModule* module, - IRModule* originalModule) + IRModule* originalModule, + CodeGenTarget target) { SharedIRBuilder* sharedBuilder = &sharedContext->sharedBuilderStorage; @@ -4053,7 +4077,7 @@ namespace Slang sharedContext->module = module; sharedContext->originalModule = originalModule; - + sharedContext->target = target; // We will populate a map with all of the IR values // that use the same mangled name, to make lookup easier // in other steps. @@ -4110,7 +4134,9 @@ namespace Slang sharedContext, compileRequest->mSession, nullptr, - originalIRModule); + originalIRModule, + target); + state->irModule = sharedContext->module; // We also need to attach the IR definitions for symbols from @@ -4123,7 +4149,6 @@ namespace Slang auto context = state->getContext(); context->shared = sharedContext; context->builder = &sharedContext->builderStorage; - context->target = target; // Create the GlobalGenericParamSubstitution for substituting global generic types // into user-provided type arguments @@ -4146,6 +4171,12 @@ namespace Slang context->globalVarLayouts.AddIfNotExists(mangledName, globalVarLayout); } + // for now, clone all unreferenced witness tables + for (auto sym :context->getSymbols()) + { + if (sym.Value->irGlobalValue->op == kIROp_witness_table) + cloneGlobalValue(context, (IRWitnessTable*)sym.Value->irGlobalValue); + } return state; } @@ -4263,7 +4294,31 @@ namespace Slang return symbol->irGlobalValue; } else - return nullptr; + { + // we don't have the required witness table yet, + // try to emit a specialize instruction to get one + auto subDeclRef = subtypeWitness->sub->AsDeclRefType(); + auto subDeclRefGen = DeclRef<Decl>(subDeclRef->declRef.decl, + createDefaultSubstitutions(context->builder->getSession(), subDeclRef->declRef.decl)); + + String genericName = getMangledNameForConformanceWitness( + subDeclRefGen, + subtypeWitness->sup); + if (context->getSymbols().TryGetValue(genericName, symbol)) + { + auto specInst = context->builder->emitSpecializeInst(subtypeWitness->sup, symbol->irGlobalValue, subDeclRef->declRef); + return specInst; + } + else + { + SLANG_UNEXPECTED("witness table not exist"); + UNREACHABLE_RETURN(nullptr); + } + } + } + else if (auto intVal = dynamic_cast<ConstantIntVal*>(val)) + { + return context->builder->getIntValue(context->shared->originalModule->session->getBuiltinType(BaseType::Int), intVal->value); } else if (auto proxyVal = dynamic_cast<IRProxyVal*>(val)) { @@ -4321,10 +4376,34 @@ namespace Slang return getIRValue(context, subst->args[argIndex]); } + else if (auto valDeclRef = declRef.As<GenericValueParamDecl>()) + { + // We have a constraint, but we need to find its index in the + // argument list of the substitutions. + UInt argIdx = 0; + bool found = false; + for (auto cd : genericDecl->Members) + { + if (cd.Ptr() == valDeclRef.getDecl()) + { + found = true; + break; + } + if (cd.As<GenericTypeParamDecl>()) + argIdx++; + else if (cd.As<GenericValueParamDecl>()) + argIdx++; + } + assert(found); + + assert(argIdx < subst->args.Count()); + + return getIRValue(context, subst->args[argIdx]); + } else { - SLANG_UNEXPECTED("unhandled case"); - return nullptr; + SLANG_UNEXPECTED("unimplemented"); + UNREACHABLE_RETURN(nullptr); } } @@ -4342,12 +4421,13 @@ namespace Slang // 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 == genSubst->genericDecl) + if(declRef.getDecl()->ParentDecl == genSubst->genericDecl && + (declRef.As<GenericTypeParamDecl>() || declRef.As<GenericValueParamDecl>()|| + declRef.As<GenericTypeConstraintDecl>())) { if (auto substVal = getSubstValue(this, declRef)) return substVal; } - int diff = 0; auto substDeclRef = declRefVal->declRef.SubstituteImpl(subst, &diff); if(!diff) @@ -4455,7 +4535,6 @@ 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; String specializedMangledName = getMangledNameForConformanceWitness(specDeclRef.Substitute(originalTable->subTypeDeclRef), specDeclRef.Substitute(originalTable->supTypeDeclRef)); @@ -4466,13 +4545,15 @@ namespace Slang // avoid it by building a dictionary ahead of time, // as is being done for the `IRSpecContext` used above. // We can probalby use the same basic context, actually. - auto module = originalTable->parentModule; - for (auto gv = module->getFirstGlobalValue(); gv; gv = gv->getNextValue()) + if (!dstTable) { - if (gv->mangledName == specMangledName) - return (IRWitnessTable*)gv; + auto module = sharedContext->module; + for (auto gv = module->getFirstGlobalValue(); gv; gv = gv->getNextValue()) + { + if (gv->mangledName == specializedMangledName) + return (IRWitnessTable*)gv; + } } - RefPtr<GenericSubstitution> newSubst = cloneSubstitutionsForSpecialization( sharedContext, specDeclRef.substitutions.genericSubstitutions, @@ -4483,13 +4564,12 @@ namespace Slang context.builder = &sharedContext->builderStorage; context.subst = specDeclRef.substitutions; context.subst.genericSubstitutions = newSubst; - // TODO: other initialization is needed here... auto specTable = cloneWitnessTableWithoutRegistering(&context, originalTable, dstTable); // Set up the clone to recognize that it is no longer generic - specTable->mangledName = specMangledName; + specTable->mangledName = specializedMangledName; specTable->genericDecl = nullptr; // Specialization of witness tables should trigger cascading specializations @@ -4499,8 +4579,9 @@ namespace Slang if (entry->satisfyingVal.usedValue->op == kIROp_Func) { IRFunc* func = (IRFunc*)entry->satisfyingVal.usedValue; - if (func->getGenericDecl()) - entry->satisfyingVal.set(getSpecializedFunc(sharedContext, func, specDeclRef)); + auto specFunc = getSpecializedFunc(sharedContext, func, specDeclRef); + entry->satisfyingVal.set(specFunc); + insertGlobalValueSymbol(sharedContext, specFunc); } } @@ -4526,13 +4607,16 @@ namespace Slang specMangledName = getMangledName(specDeclRef); else specMangledName = mangleSpecializedFuncName(genericFunc->mangledName, specDeclRef.substitutions); - + RefPtr<IRSpecSymbol> symb; + if (sharedContext->symbols.TryGetValue(specMangledName, symb)) + { + return (IRFunc*)(symb->irGlobalValue); + } // TODO: This is a terrible linear search, and we should // avoid it by building a dictionary ahead of time, // as is being done for the `IRSpecContext` used above. // We can probalby use the same basic context, actually. - auto module = genericFunc->parentModule; - for (auto gv = module->getFirstGlobalValue(); gv; gv = gv->getNextValue()) + for (auto gv = sharedContext->module->getFirstGlobalValue(); gv; gv = gv->getNextValue()) { if (gv->mangledName == specMangledName) return (IRFunc*) gv; @@ -4639,7 +4723,8 @@ namespace Slang // are known, and specialize the callee based on those // known values. void specializeGenerics( - IRModule* module) + IRModule* module, + CodeGenTarget target) { IRSharedSpecContext sharedContextStorage; auto sharedContext = &sharedContextStorage; @@ -4648,7 +4733,8 @@ namespace Slang sharedContext, module->session, module, - module); + module, + target); // Our goal here is to find `specialize` instructions that // can be replaced with references to a suitably sepcialized @@ -4895,11 +4981,10 @@ namespace Slang table = findWitnessTableByName(genericWitnessTableName); SLANG_ASSERT(table); WitnessTableSpecializationWorkItem workItem; - workItem.srcTable = (IRWitnessTable*)table; + workItem.srcTable = (IRWitnessTable*)cloneGlobalValue(context, (IRWitnessTable*)(table)); workItem.dstTable = context->builder->createWitnessTable(); workItem.dstTable->mangledName = getMangledNameForConformanceWitness(subDeclRefType->declRef, subtypeWitness->sup); workItem.specDeclRef = subDeclRefType->declRef; - registerClonedValue(context, workItem.dstTable, workItem.srcTable); witnessTablesToSpecailize.Add(workItem); table = workItem.dstTable; } diff --git a/source/slang/legalize-types.cpp b/source/slang/legalize-types.cpp index 211685aa2..d1cef4dac 100644 --- a/source/slang/legalize-types.cpp +++ b/source/slang/legalize-types.cpp @@ -916,7 +916,7 @@ LegalType legalizeType( } legalType = builder.getResult(); - context->mapDeclRefToLegalType.Add(declRef, legalType); + context->mapDeclRefToLegalType.AddIfNotExists(declRef, legalType); return legalType; } diff --git a/source/slang/lower-to-ir.cpp b/source/slang/lower-to-ir.cpp index 5e7e05a23..5d710725a 100644 --- a/source/slang/lower-to-ir.cpp +++ b/source/slang/lower-to-ir.cpp @@ -1021,6 +1021,7 @@ RefPtr<IRFuncType> getFuncType( return funcType; } +SubstitutionSet lowerSubstitutions(IRGenContext* context, SubstitutionSet subst); // struct ValLoweringVisitor : ValVisitor<ValLoweringVisitor, LoweredValInfo, LoweredTypeInfo> @@ -1080,8 +1081,6 @@ struct ValLoweringVisitor : ValVisitor<ValLoweringVisitor, LoweredValInfo, Lower // TODO: actually test what module the type is coming from. lowerDecl(context, type->declRef); - - return LoweredTypeInfo(type); } @@ -3006,6 +3005,11 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo> return globalVal; } + LoweredValInfo visitGenericValueParamDecl(GenericValueParamDecl* decl) + { + return LoweredValInfo::simple(context->irBuilder->getDeclRefVal(DeclRefBase(decl))); + } + LoweredValInfo visitVarDeclBase(VarDeclBase* decl) { // Detect global (or effectively global) variables @@ -3733,7 +3737,10 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo> if (auto innerFuncDecl = genDecl->inner->As<FuncDecl>()) return lowerFuncDecl(innerFuncDecl); else if (auto innerStructDecl = genDecl->inner->As<StructDecl>()) + { + visitAggTypeDecl(innerStructDecl); return LoweredValInfo(); + } SLANG_RELEASE_ASSERT(false); UNREACHABLE_RETURN(LoweredValInfo()); } @@ -3910,6 +3917,32 @@ RefPtr<GenericSubstitution> lowerGenericSubstitutions( return result; } +RefPtr<GlobalGenericParamSubstitution> lowerGlobalGenericSubstitutions( + IRGenContext* context, + GlobalGenericParamSubstitution* genSubst) +{ + if (!genSubst) + return nullptr; + RefPtr<GlobalGenericParamSubstitution> result; + RefPtr<GlobalGenericParamSubstitution> newSubst = new GlobalGenericParamSubstitution(); + newSubst->actualType = lowerSubstitutionArg(context, genSubst->actualType); + newSubst->paramDecl = genSubst->paramDecl; + for (auto & tbl : genSubst->witnessTables) + { + auto ntbl = tbl; + ntbl.Value = lowerSubstitutionArg(context, tbl.Value); + newSubst->witnessTables.Add(ntbl); + } + result = newSubst; + if (genSubst->outer) + { + result->outer = lowerGlobalGenericSubstitutions( + context, + genSubst->outer); + } + return result; +} + RefPtr<ThisTypeSubstitution> lowerThisTypeSubstitution( IRGenContext* context, ThisTypeSubstitution* thisSubst) @@ -3926,7 +3959,7 @@ SubstitutionSet lowerSubstitutions(IRGenContext* context, SubstitutionSet subst) SubstitutionSet rs; rs.genericSubstitutions = lowerGenericSubstitutions(context, subst.genericSubstitutions); rs.thisTypeSubstitution = lowerThisTypeSubstitution(context, subst.thisTypeSubstitution); - rs.globalGenParamSubstitutions = subst.globalGenParamSubstitutions; + rs.globalGenParamSubstitutions = lowerGlobalGenericSubstitutions(context, subst.globalGenParamSubstitutions); return rs; } @@ -3973,10 +4006,10 @@ LoweredValInfo maybeEmitSpecializeInst(IRGenContext* context, // need to walk through those and replace things in // cases where the `Val`s used for substitution should // lower to something other than their original form. - auto lowedNewSubst = lowerGenericSubstitutions(context, newSubst); - DeclRef<Decl> newDeclRef = DeclRef<Decl>(declRef.decl, - SubstitutionSet(lowedNewSubst, declRef.substitutions.thisTypeSubstitution, - declRef.substitutions.globalGenParamSubstitutions)); + SubstitutionSet oldSubst = declRef.substitutions; + oldSubst.genericSubstitutions = newSubst; + auto lowedNewSubst = lowerSubstitutions(context, oldSubst); + DeclRef<Decl> newDeclRef = DeclRef<Decl>(declRef.decl, lowedNewSubst); RefPtr<Type> type; if (auto declType = val->getType()) @@ -4014,9 +4047,9 @@ static void lowerEntryPointToIR( return; } // we need to lower all global type arguments as well + auto loweredEntryPointFunc = ensureDecl(context, entryPointFuncDecl); for (auto arg : entryPointRequest->genericParameterTypes) lowerType(context, arg); - auto loweredEntryPointFunc = ensureDecl(context, entryPointFuncDecl); } #if 0 diff --git a/source/slang/reflection.cpp b/source/slang/reflection.cpp index c9de75d6e..b0be58274 100644 --- a/source/slang/reflection.cpp +++ b/source/slang/reflection.cpp @@ -433,20 +433,8 @@ SLANG_API SlangReflectionType * spReflection_FindTypeByName(SlangReflection * re auto context = convert(reflection); auto compileRequest = context->targetRequest->compileRequest; - RefPtr<Type> result; - if (compileRequest->types.TryGetValue(name, result)) - return (SlangReflectionType*)result.Ptr(); - - auto nameObj = compileRequest->getNamePool()->getName(name); - Decl* resultDecl = compileRequest->lookupGlobalDecl(nameObj); - if (resultDecl) - { - RefPtr<DeclRefType> declRefType = new DeclRefType(); - declRefType->declRef.decl = resultDecl; - compileRequest->types[name] = declRefType; - return (SlangReflectionType*)declRefType.Ptr(); - } - return nullptr; + RefPtr<Type> result = compileRequest->getTypeFromString(name); + return (SlangReflectionType*)result.Ptr(); } SLANG_API SlangReflectionTypeLayout* spReflection_GetTypeLayout( diff --git a/source/slang/slang.cpp b/source/slang/slang.cpp index d907e7614..4c9ecf8a8 100644 --- a/source/slang/slang.cpp +++ b/source/slang/slang.cpp @@ -131,6 +131,7 @@ RefPtr<Expr> CompileRequest::parseTypeString(TranslationUnitRequest * translatio Slang::SourceFile srcFile; srcFile.content = typeStr; DiagnosticSink sink; + sink.sourceManager = sourceManager; auto tokens = preprocessSource( &srcFile, &sink, @@ -140,6 +141,34 @@ RefPtr<Expr> CompileRequest::parseTypeString(TranslationUnitRequest * translatio return parseTypeFromSourceFile(translationUnit, tokens, &sink, scope); } +RefPtr<Type> checkProperType(TranslationUnitRequest * tu, TypeExp typeExp); +Type* CompileRequest::getTypeFromString(String typeStr) +{ + RefPtr<Type> type; + if (types.TryGetValue(typeStr, type)) + return type; + auto translationUnit = translationUnits.First(); + List<RefPtr<Scope>> scopesToTry; + for (auto tu : translationUnits) + scopesToTry.Add(tu->SyntaxNode->scope); + for (auto & module : loadedModulesList) + scopesToTry.Add(module->moduleDecl->scope); + // parse type name + for (auto & s : scopesToTry) + { + RefPtr<Expr> typeExpr = parseTypeString(translationUnit, + typeStr, s); + type = checkProperType(translationUnit, TypeExp(typeExpr)); + if (type) + break; + } + if (type) + { + types[typeStr] = type; + } + return type.Ptr(); +} + void CompileRequest::parseTranslationUnit( TranslationUnitRequest* translationUnit) { diff --git a/source/slang/syntax.cpp b/source/slang/syntax.cpp index 85a702726..ab4a5f94c 100644 --- a/source/slang/syntax.cpp +++ b/source/slang/syntax.cpp @@ -362,12 +362,14 @@ void Type::accept(IValVisitor* visitor, void* extra) { int diff = 0; auto elementType = baseType->SubstituteImpl(subst, &diff).As<Type>(); + auto arrlen = ArrayLength->SubstituteImpl(subst, &diff).As<IntVal>(); + SLANG_ASSERT(arrlen); if (diff) { *ioDiff = 1; auto rsType = getArrayType( elementType, - ArrayLength); + arrlen); return rsType; } return this; |
