diff --git a/tslang/lib/TypeScript/CMakeLists.txt b/tslang/lib/TypeScript/CMakeLists.txt index eafbda06..db27e58a 100644 --- a/tslang/lib/TypeScript/CMakeLists.txt +++ b/tslang/lib/TypeScript/CMakeLists.txt @@ -22,6 +22,7 @@ add_mlir_dialect_library(MLIRTypeScript MLIRGenExpressions.cpp MLIRGenFunctions.cpp MLIRGenGenerics.cpp + MLIRGenInterfaces.cpp MLIRGenModule.cpp MLIRGenStatements.cpp MLIRGenTypes.cpp diff --git a/tslang/lib/TypeScript/MLIRGenImpl.h b/tslang/lib/TypeScript/MLIRGenImpl.h index 6530bb63..d488d739 100644 --- a/tslang/lib/TypeScript/MLIRGenImpl.h +++ b/tslang/lib/TypeScript/MLIRGenImpl.h @@ -10852,178 +10852,7 @@ class MLIRGenImpl return mlir::failure(); } - mlir::LogicalResult mlirGen(EnumDeclaration enumDeclarationAST, const GenContext &genContext) - { - auto namePtr = MLIRHelper::getName(enumDeclarationAST->name, stringAllocator); - if (namePtr.empty()) - { - return mlir::failure(); - } - - SymbolTableScopeT varScope(symbolTable); - - SmallVector enumLiteralTypes; - StringMap enumValues; - - auto appending = false; - if (getEnumsMap().contains(namePtr)) - { - auto dict = getEnumsMap().lookup(namePtr).second; - for (auto key : dict) - { - enumValues[key.getName()] = key.getValue(); - } - - appending = true; - } - else - { - getEnumsMap().insert( - { namePtr, { getEnumType().getElementType(), mlir::DictionaryAttr::get(builder.getContext(), {}) } }); - } - - auto &enumInfo = getEnumsMap()[namePtr]; - - auto activeBits = 32; - mlir::IntegerType::SignednessSemantics currentEnumValueSigedness = mlir::IntegerType::SignednessSemantics::Signless; - llvm::APInt currentEnumValue(32, 0); - for (auto enumMember : enumDeclarationAST->members) - { - auto location = loc(enumMember); - - auto memberNamePtr = MLIRHelper::getName(enumMember->name, stringAllocator); - if (memberNamePtr.empty()) - { - return mlir::failure(); - } - - mlir::Attribute enumValueAttr; - if (enumMember->initializer) - { - GenContext enumValueGenContext(genContext); - enumValueGenContext.allowConstEval = true; - auto result = mlirGen(enumMember->initializer, enumValueGenContext); - EXIT_IF_FAILED_OR_NO_VALUE(result) - auto enumValue = V(result); - - LLVM_DEBUG(llvm::dbgs() << "\n!! enum member: [ " << memberNamePtr << " ] = [ " << enumValue << " ]\n"); - - if (auto constOp = dyn_cast(enumValue.getDefiningOp())) - { - enumValueAttr = constOp.getValueAttr(); - if (auto intAttr = dyn_cast(enumValueAttr)) - { - if (intAttr.getType().isSignlessInteger()) - { - currentEnumValueSigedness = mlir::IntegerType::SignednessSemantics::Signless; - } - else if (intAttr.getType().isSignedInteger()) - { - currentEnumValueSigedness = mlir::IntegerType::SignednessSemantics::Signed; - } - else if (intAttr.getType().isUnsignedInteger()) - { - currentEnumValueSigedness = mlir::IntegerType::SignednessSemantics::Unsigned; - } - - currentEnumValue = intAttr.getValue(); - auto currentActiveBits = (int)intAttr.getValue().getActiveBits(); - if (currentActiveBits > activeBits) - { - activeBits = currentActiveBits; - } - } - } - else - { - emitError(loc(enumMember->initializer)) - << "enum member '" << memberNamePtr << "' must be constant"; - return mlir::failure(); - } - - enumLiteralTypes.push_back(enumValue.getType()); - - auto varDecl = std::make_shared(memberNamePtr, enumValue.getType(), location); - DECLARE(varDecl, enumValue); - - } - else - { - if (appending && currentEnumValue == 0 && stage == Stages::Discovering && !enumValues.contains(memberNamePtr)) - { - emitError(loc(enumMember)) - << "In an enum with multiple declarations, only one declaration can omit an initializer for its first enum element"; - return mlir::failure(); - } - - auto typeInt = mlir::IntegerType::get(builder.getContext(), activeBits, currentEnumValueSigedness); - enumValueAttr = builder.getIntegerAttr(typeInt, currentEnumValue); - auto indexType = mlir_ts::LiteralType::get(enumValueAttr, typeInt); - enumLiteralTypes.push_back(indexType); - - LLVM_DEBUG(llvm::dbgs() << "\n!! enum member: " << memberNamePtr << " <- " << indexType << "\n"); - - auto varDecl = std::make_shared(memberNamePtr, indexType, location); - auto enumVal = builder.create(location, indexType, enumValueAttr); - DECLARE(varDecl, enumVal); - } - - LLVM_DEBUG(llvm::dbgs() << "\n!! enum: " << namePtr << " value attr: " << enumValueAttr << "\n"); - - enumValues[memberNamePtr] = enumValueAttr; - - // update enum to support req. access - SmallVector namedEnumValues; - for (auto &key : enumValues) - { - namedEnumValues.push_back({builder.getStringAttr(key.first()), key.second}); - } - - enumInfo.second = mlir::DictionaryAttr::get(builder.getContext(), namedEnumValues /*adjustedEnumValues*/); - - currentEnumValue++; - } - - auto location = loc(enumDeclarationAST); - auto storeType = mth.getUnionTypeWithMerge(location, enumLiteralTypes); - - LLVM_DEBUG(llvm::dbgs() << "\n!! enum: " << namePtr << " storage type: " << storeType << "\n"); - - // update enum to support req. access - enumInfo.first = storeType; - - // register fullName for enum - auto fullNamePtr = getFullNamespaceName(namePtr); - - auto enumType = getEnumType( - mlir::FlatSymbolRefAttr::get(builder.getContext(), fullNamePtr), - enumInfo.first, - enumInfo.second); - - EnumInfo::TypePtr newEnumPtr; - if (fullNameEnumsMap.count(fullNamePtr)) - { - newEnumPtr = fullNameEnumsMap.lookup(fullNamePtr); - newEnumPtr->enumType = enumType; - } - else - { - // register class - newEnumPtr = std::make_shared(); - newEnumPtr->name = namePtr; - newEnumPtr->fullName = fullNamePtr; - newEnumPtr->elementNamespace = currentNamespace; - newEnumPtr->enumType = enumType; - fullNameEnumsMap.insert(fullNamePtr, newEnumPtr); - } - - if (getExportModifier(enumDeclarationAST)) - { - addEnumDeclarationToExport(namePtr, currentNamespace, enumType); - } - - return mlir::success(); - } + mlir::LogicalResult mlirGen(EnumDeclaration enumDeclarationAST, const GenContext &genContext); mlir::LogicalResult registerGenericClass(ClassLikeDeclaration classDeclarationAST, const GenContext &genContext); @@ -11362,78 +11191,7 @@ class MLIRGenImpl const GenContext &genContext); ValueOrLogicalResult mlirGenCreateInterfaceVTableForObject(mlir::Location location, mlir::Value in, - mlir_ts::ObjectType objectType, InterfaceInfo::TypePtr newInterfacePtr, const GenContext &genContext) - { - auto fullObjectInterfaceVTableFieldName = interfaceVTableNameForObject(objectType, newInterfacePtr); - auto existValue = resolveFullNameIdentifier(location, fullObjectInterfaceVTableFieldName, true, genContext); - if (existValue) - { - return existValue; - } - - if (mlir::succeeded( - mlirGenObjectVirtualTableDefinitionForInterface(location, objectType, newInterfacePtr, genContext))) - { - auto globalVTableRefValue = resolveFullNameIdentifier(location, fullObjectInterfaceVTableFieldName, true, genContext); - - // we need to update methods references in VTable with functions from object; - if (newInterfacePtr->methods.size() > 0) { - - mlir_ts::TupleType storeType; - if (auto objectStoreType = dyn_cast(objectType.getStorageType())) - { - storeType = mlir_ts::TupleType::get(builder.getContext(), objectStoreType.getFields()); - } - else if (auto tupleType = dyn_cast(objectType.getStorageType())) - { - storeType = tupleType; - } - else - { - return mlir::failure(); - } - - // match VTable - // 1) clone vtable - auto vtableType = mlir::cast(mlir::cast(globalVTableRefValue.getType()).getElementType()); - auto valueVTable = builder.create(location, vtableType, globalVTableRefValue); - auto varVTable = builder.create(location, globalVTableRefValue.getType(), valueVTable, - builder.getBoolAttr(false), builder.getIndexAttr(0)); - - for (auto& method : newInterfacePtr->methods) - { - auto index = mth.getFieldIndexByFieldName(storeType, builder.getStringAttr(method.name)); - if (index == -1) - { - return mlir::failure(); - } - - auto fieldInfo = mth.getFieldInfoByIndex(storeType, index); - - auto methodRef = builder.create(location, mlir_ts::RefType::get(fieldInfo.type), in, index); - - LLVM_DEBUG(llvm::dbgs() << "\n!!\n\t vtable method: " << method.name - << "\n\t object method ref: " << V(methodRef) << "\n\n";); - - // where to save - auto fieldInfoVT = mth.getFieldInfoByIndex(vtableType, method.virtualIndex); - auto methodRefVT = builder.create(location, fieldInfoVT.type, varVTable, method.virtualIndex); - - LLVM_DEBUG(llvm::dbgs() << "\n!!\n\t vtable method: " << method.name - << "\n\t vtable method ref: " << V(methodRefVT) << "\n\n";); - - builder.create(location, methodRefVT, methodRef); - } - - // patched VTable - return V(varVTable); - } - - return globalVTableRefValue; - } - - return mlir::failure(); - } + mlir_ts::ObjectType objectType, InterfaceInfo::TypePtr newInterfacePtr, const GenContext &genContext); StringRef interfaceVTableNameForClass(ClassInfo::TypePtr newClassPtr, InterfaceInfo::TypePtr newInterfacePtr) { @@ -11459,120 +11217,7 @@ class MLIRGenImpl mlir::LogicalResult mlirGenObjectVirtualTableDefinitionForInterface(mlir::Location location, mlir_ts::ObjectType objectType, InterfaceInfo::TypePtr newInterfacePtr, - const GenContext &genContext) - { - - MLIRCodeLogic mcl(builder, compileOptions); - - auto storeType = objectType.getStorageType(); - - // TODO: should object accept only ObjectStorageType? - if (auto objectStoreType = dyn_cast(storeType)) - { - storeType = mlir_ts::TupleType::get(builder.getContext(), objectStoreType.getFields()); - } - - auto tupleStorageType = mlir::cast(mth.convertConstTupleTypeToTupleType(storeType)); - - SmallVector virtualTable; - auto result = getInterfaceVirtualTableForObject(location, tupleStorageType, newInterfacePtr, virtualTable); - if (mlir::failed(result)) - { - return result; - } - - // register global - auto fullClassInterfaceVTableFieldName = interfaceVTableNameForObject(objectType, newInterfacePtr); - registerVariable( - location, fullClassInterfaceVTableFieldName, true, VariableType::Var, - [&](mlir::Location location, const GenContext &genContext) { - // build vtable from names of methods - - auto virtTuple = getVirtualTableType(virtualTable); - - mlir::Value vtableValue = builder.create(location, virtTuple); - auto fieldIndex = 0; - for (auto methodOrField : virtualTable) - { - if (methodOrField.isField) - { - auto nullObj = builder.create(location, getNullType()); - if (!methodOrField.isMissing) - { - // TODO: test cast result - auto objectNull = cast(location, objectType, nullObj, genContext, true); - if (!objectNull) - { - return TypeValueInitType{mlir::Type(), mlir::Value(), TypeProvided::Yes}; - } - - auto fieldValue = mlirGenPropertyAccessExpression(location, objectNull, - methodOrField.fieldInfo.id, genContext); - assert(fieldValue); - if (!fieldValue) - { - return TypeValueInitType{mlir::Type(), mlir::Value(), TypeProvided::Yes}; - } - - auto fieldRef = mcl.GetReferenceFromValue(location, fieldValue); - - LLVM_DEBUG(llvm::dbgs() << "\n!!\n\t vtable field: " << methodOrField.fieldInfo.id - << "\n\t type: " << methodOrField.fieldInfo.type - << "\n\t provided data: " << fieldRef << "\n\n";); - - if (isa(fieldRef.getType())) - { - fieldRef = cast(location, mlir_ts::RefType::get(methodOrField.fieldInfo.type), fieldRef, - genContext); - } - else - { - assert(mlir::cast(fieldRef.getType()).getElementType() == - methodOrField.fieldInfo.type); - } - - // insert &(null)->field - vtableValue = builder.create( - location, virtTuple, fieldRef, vtableValue, - MLIRHelper::getStructIndex(builder, fieldIndex)); - } - else - { - // null value, as missing field/method - // auto nullObj = builder.create(location, getNullType()); - auto negative1 = builder.create(location, builder.getI64Type(), - mth.getI64AttrValue(-1)); - auto castedPtr = cast(location, mlir_ts::RefType::get(methodOrField.fieldInfo.type), - negative1, genContext); - vtableValue = builder.create( - location, virtTuple, castedPtr, vtableValue, - MLIRHelper::getStructIndex(builder, fieldIndex)); - } - } - else - { - llvm_unreachable("not implemented yet"); - /* - auto methodConstName = builder.create( - location, methodOrField.methodInfo.funcOp.getType(), - mlir::FlatSymbolRefAttr::get(builder.getContext(), - methodOrField.methodInfo.funcOp.getSymName())); - - vtableValue = - builder.create(location, virtTuple, methodConstName, vtableValue, - MLIRHelper::getStructIndex(rewriter, fieldIndex)); - */ - } - - fieldIndex++; - } - - return TypeValueInitType{virtTuple, vtableValue, TypeProvided::Yes}; - }, - genContext); - - return mlir::success(); - } + const GenContext &genContext); mlir::LogicalResult mlirGenClassVirtualTableDefinitionForInterface(mlir::Location location, ClassInfo::TypePtr newClassPtr, @@ -11971,44 +11616,7 @@ class MLIRGenImpl } mlir::LogicalResult registerGenericInterface(InterfaceDeclaration interfaceDeclarationAST, - const GenContext &genContext) - { - auto name = MLIRHelper::getName(interfaceDeclarationAST->name); - if (!name.empty()) - { - auto namePtr = StringRef(name).copy(stringAllocator); - auto fullNamePtr = getFullNamespaceName(namePtr); - if (fullNameGenericInterfacesMap.count(fullNamePtr)) - { - return mlir::success(); - } - - llvm::SmallVector typeParameters; - if (mlir::failed( - processTypeParameters(interfaceDeclarationAST->typeParameters, typeParameters, genContext))) - { - return mlir::failure(); - } - - GenericInterfaceInfo::TypePtr newGenericInterfacePtr = std::make_shared(); - newGenericInterfacePtr->name = namePtr; - newGenericInterfacePtr->fullName = fullNamePtr; - newGenericInterfacePtr->elementNamespace = currentNamespace; - newGenericInterfacePtr->typeParams = typeParameters; - newGenericInterfacePtr->interfaceDeclaration = interfaceDeclarationAST; - newGenericInterfacePtr->sourceFile = sourceFile; - newGenericInterfacePtr->fileName = mainSourceFileName; - - mlirGenInterfaceType(newGenericInterfacePtr, genContext); - - getGenericInterfacesMap().insert({namePtr, newGenericInterfacePtr}); - fullNameGenericInterfacesMap.insert(fullNamePtr, newGenericInterfacePtr); - - return mlir::success(); - } - - return mlir::failure(); - } + const GenContext &genContext); void appendSpecializedTypeNames(std::string &name, NodeArray typeParams, const GenContext &genContext) @@ -12123,175 +11731,17 @@ class MLIRGenImpl } InterfaceInfo::TypePtr mlirGenInterfaceInfo(InterfaceDeclaration interfaceDeclarationAST, bool &declareInterface, - const GenContext &genContext) - { - auto name = getNameWithArguments(interfaceDeclarationAST, genContext); - return mlirGenInterfaceInfo(name, declareInterface, genContext); - } + const GenContext &genContext); InterfaceInfo::TypePtr mlirGenInterfaceInfo(const std::string &name, bool &declareInterface, - const GenContext &genContext) - { - declareInterface = false; - - auto namePtr = StringRef(name).copy(stringAllocator); - auto fullNamePtr = getFullNamespaceName(namePtr); - - InterfaceInfo::TypePtr newInterfacePtr; - if (fullNameInterfacesMap.count(fullNamePtr)) - { - newInterfacePtr = fullNameInterfacesMap.lookup(fullNamePtr); - getInterfacesMap().insert({namePtr, newInterfacePtr}); - declareInterface = !newInterfacePtr->interfaceType; - } - else - { - // register class - newInterfacePtr = std::make_shared(); - newInterfacePtr->name = namePtr; - newInterfacePtr->fullName = fullNamePtr; - newInterfacePtr->elementNamespace = currentNamespace; - - getInterfacesMap().insert({namePtr, newInterfacePtr}); - fullNameInterfacesMap.insert(fullNamePtr, newInterfacePtr); - declareInterface = true; - } - - if (declareInterface && mlir::succeeded(mlirGenInterfaceType(newInterfacePtr, genContext))) - { - newInterfacePtr->typeParamsWithArgs = genContext.typeParamsWithArgs; - } - - return newInterfacePtr; - } + const GenContext &genContext); mlir::LogicalResult mlirGenInterfaceHeritageClauseExtends(InterfaceDeclaration interfaceDeclarationAST, InterfaceInfo::TypePtr newInterfacePtr, HeritageClause heritageClause, int &orderWeight, bool declareClass, - const GenContext &genContext) - { - if (heritageClause->token != SyntaxKind::ExtendsKeyword) - { - return mlir::success(); - } - - for (auto &extendsType : heritageClause->types) - { - auto result = mlirGen(extendsType, genContext); - EXIT_IF_FAILED(result); - auto ifaceType = V(result); - auto success = false; - mlir::TypeSwitch(ifaceType.getType()) - .template Case([&](auto interfaceType) { - auto interfaceInfo = getInterfaceInfoByFullName(interfaceType.getName().getValue()); - if (interfaceInfo) - { - newInterfacePtr->extends.push_back({-1, interfaceInfo}); - success = true; - } - }) - .template Case([&](auto tupleType) { - llvm::SmallVector destTupleFields; - if (mlir::succeeded(mth.getFields(tupleType, destTupleFields))) - { - orderWeight++; - success = true; - for (auto field : destTupleFields) - success &= mlir::succeeded( - mlirGenInterfaceAddFieldMember(newInterfacePtr, field.id, field.type, field.isConditional, orderWeight)); - } - }) - .Default([&](auto type) { llvm_unreachable("not implemented"); }); - - if (!success) - { - return mlir::failure(); - } - } - - return mlir::success(); - } - - mlir::LogicalResult mlirGen(InterfaceDeclaration interfaceDeclarationAST, const GenContext &genContext) - { - // do not proceed for Generic Interfaces for declaration - if (interfaceDeclarationAST->typeParameters.size() > 0 && genContext.typeParamsWithArgs.size() == 0) - { - return registerGenericInterface(interfaceDeclarationAST, genContext); - } - - auto declareInterface = false; - auto newInterfacePtr = mlirGenInterfaceInfo(interfaceDeclarationAST, declareInterface, genContext); - if (!newInterfacePtr) - { - return mlir::failure(); - } - - // do not process specialized interface second time; - if (!declareInterface && interfaceDeclarationAST->typeParameters.size() > 0 && - genContext.typeParamsWithArgs.size() > 0) - { - return mlir::success(); - } - - auto location = loc(interfaceDeclarationAST); - - auto ifaceGenContext = GenContext(genContext); - ifaceGenContext.thisType = newInterfacePtr->interfaceType; - - auto orderWeight = 0; - for (auto &heritageClause : interfaceDeclarationAST->heritageClauses) - { - if (mlir::failed(mlirGenInterfaceHeritageClauseExtends(interfaceDeclarationAST, newInterfacePtr, - heritageClause, orderWeight, declareInterface, genContext))) - { - return mlir::failure(); - } - } - - newInterfacePtr->recalcOffsets(); - - // clear all flags - for (auto &interfaceMember : interfaceDeclarationAST->members) - { - interfaceMember->processed = false; - } - - // add methods when we have classType - auto notResolved = 0; - do - { - auto lastTimeNotResolved = notResolved; - notResolved = 0; - - for (auto &interfaceMember : interfaceDeclarationAST->members) - { - orderWeight++; - if (mlir::failed(mlirGenInterfaceMethodMember( - interfaceDeclarationAST, newInterfacePtr, interfaceMember, orderWeight, declareInterface, ifaceGenContext))) - { - notResolved++; - } - } - - // repeat if not all resolved - if (lastTimeNotResolved > 0 && lastTimeNotResolved == notResolved) - { - // interface can depend on other interface declarations - // theModule.emitError("can't resolve dependencies in intrerface: ") << newInterfacePtr->name; - return mlir::failure(); - } - - } while (notResolved > 0); - - // add to export if any - if (auto hasExport = getExportModifier(interfaceDeclarationAST)) - { - addInterfaceDeclarationToExport(newInterfacePtr); - } + const GenContext &genContext); - return mlir::success(); - } + mlir::LogicalResult mlirGen(InterfaceDeclaration interfaceDeclarationAST, const GenContext &genContext); template mlir::LogicalResult mlirGenInterfaceType(T newInterfacePtr, const GenContext &genContext) { @@ -12304,44 +11754,7 @@ class MLIRGenImpl return mlir::failure(); } - mlir::LogicalResult mlirGenInterfaceAddFieldMember(InterfaceInfo::TypePtr newInterfacePtr, mlir::Attribute fieldId, mlir::Type typeIn, bool isConditional, int orderWeight, bool declareInterface = true) - { - auto &fieldInfos = newInterfacePtr->fields; - auto type = typeIn; - - // fix type for fields with FuncType - if (auto hybridFuncType = dyn_cast(type)) - { - - auto funcType = getFunctionType(hybridFuncType.getInputs(), hybridFuncType.getResults(), hybridFuncType.isVarArg()); - type = mth.getFunctionTypeAddingFirstArgType(funcType, getOpaqueType()); - } - else if (auto funcType = dyn_cast(type)) - { - - type = mth.getFunctionTypeAddingFirstArgType(funcType, getOpaqueType()); - } - - if (mth.isNoneType(type)) - { - LLVM_DEBUG(dbgs() << "\n!! interface field: " << fieldId << " FAILED\n"); - return mlir::failure(); - } - - auto fieldIndex = newInterfacePtr->getFieldIndex(fieldId); - if (fieldIndex == -1) - { - fieldInfos.push_back({fieldId, type, isConditional, orderWeight, newInterfacePtr->getNextVTableMemberIndex()}); - } - else - { - // update - fieldInfos[fieldIndex].type = type; - fieldInfos[fieldIndex].isConditional = isConditional; - } - - return mlir::success(); - } + mlir::LogicalResult mlirGenInterfaceAddFieldMember(InterfaceInfo::TypePtr newInterfacePtr, mlir::Attribute fieldId, mlir::Type typeIn, bool isConditional, int orderWeight, bool declareInterface = true); mlir::LogicalResult addInterfaceMethod(mlir::Location location, InterfaceInfo::TypePtr newInterfacePtr, llvm::SmallVector &methodInfos, StringRef methodName, mlir_ts::FunctionType funcType, bool isConditional, @@ -12414,235 +11827,12 @@ class MLIRGenImpl mlir::LogicalResult mlirGenInterfaceMethodMember(InterfaceDeclaration interfaceDeclarationAST, InterfaceInfo::TypePtr newInterfacePtr, TypeElement interfaceMember, int orderWeight, bool declareInterface, - const GenContext &genContext) - { - if (interfaceMember->processed) - { - return mlir::success(); - } - - auto location = loc(interfaceMember); - - auto &methodInfos = newInterfacePtr->methods; - - mlir::Value initValue; - mlir::Attribute fieldId; - mlir::Type type; - StringRef memberNamePtr; - - MLIRCodeLogic mcl(builder, compileOptions); - - SyntaxKind kind = interfaceMember; - if (kind == SyntaxKind::PropertySignature) - { - // property declaration - auto propertySignature = interfaceMember.as(); - auto isConditional = !!propertySignature->questionToken; - - fieldId = TupleFieldName(propertySignature->name, genContext); - - auto [type, init, typeProvided] = getTypeAndInit(propertySignature, genContext); - if (!type) - { - return mlir::failure(); - } - - if (mlir::failed(mlirGenInterfaceAddFieldMember(newInterfacePtr, fieldId, type, isConditional, orderWeight, declareInterface))) - { - return mlir::failure(); - } - } - else if (kind == SyntaxKind::MethodSignature - || kind == SyntaxKind::ConstructSignature || kind == SyntaxKind::CallSignature - || kind == SyntaxKind::GetAccessor || kind == SyntaxKind::SetAccessor) - { - auto methodSignature = interfaceMember.as(); - auto isConditional = !!methodSignature->questionToken; - - newInterfacePtr->hasNew |= kind == SyntaxKind::ConstructSignature; - // we need this code to add "THIS" param to declaration - interfaceMember->parent = interfaceDeclarationAST; - - std::string methodName; - std::string propertyName; - mlir_ts::FunctionType funcType; - if (mlir::failed(getInterfaceMethodNameAndType(location, newInterfacePtr->interfaceType, methodSignature, - methodName, propertyName, funcType, genContext))) - { - return mlir::failure(); - } - - if (mlir::failed(addInterfaceMethod(location, newInterfacePtr, methodInfos, - methodName, funcType, isConditional, orderWeight, declarationMode, genContext))) - { - return mlir::failure(); - } - - // add info about property - if (kind == SyntaxKind::GetAccessor || kind == SyntaxKind::SetAccessor) - { - auto accessor = newInterfacePtr->findAccessor(propertyName); - - auto &accessors = newInterfacePtr->accessors; - if (accessor == nullptr) - { - if (kind == SyntaxKind::GetAccessor) - { - accessors.push_back({funcType.getResult(0), propertyName, methodName, ""}); - } - else - { - accessors.push_back({funcType.getInputs().back(), propertyName, "", methodName}); - } - } - else - { - if (kind == SyntaxKind::GetAccessor) - { - accessor->getMethod = methodName; - } - else - { - accessor->setMethod = methodName; - } - } - } - - methodSignature->processed = true; - } - else if (kind == SyntaxKind::IndexSignature) - { - auto methodSignature = interfaceMember.as(); - // we need this code to add "THIS" param to declaration - interfaceMember->parent = interfaceDeclarationAST; - - std::string methodName; - std::string propertyName; - mlir_ts::FunctionType funcType; - if (mlir::failed(getInterfaceMethodNameAndType( - location, newInterfacePtr->interfaceType, methodSignature, methodName, propertyName, funcType, genContext))) - { - return mlir::failure(); - } - - // add get method - if (mlir::failed(addInterfaceMethod(location, newInterfacePtr, methodInfos, - INDEX_ACCESS_GET_FIELD_NAME, mth.getIndexGetFunctionType(funcType), true, orderWeight, declarationMode, genContext))) - { - return mlir::failure(); - } - - if (mlir::failed(addInterfaceMethod(location, newInterfacePtr, methodInfos, - INDEX_ACCESS_SET_FIELD_NAME, mth.getIndexSetFunctionType(funcType), true, orderWeight, declarationMode, genContext))) - { - return mlir::failure(); - } - - auto found = llvm::find_if(newInterfacePtr->indexes, [&] (auto indexInfo) { - return indexInfo.indexSignature == funcType; - }); - - if (found == newInterfacePtr->indexes.end()) - { - newInterfacePtr->indexes.push_back({funcType, INDEX_ACCESS_GET_FIELD_NAME, INDEX_ACCESS_SET_FIELD_NAME}); - } - - methodSignature->processed = true; - } - else - { - llvm_unreachable("not implemented"); - } - - return mlir::success(); - } - - std::tuple getNameForMethod(SignatureDeclarationBase methodSignature, const GenContext &genContext) - { - auto [attr, result] = getNameFromComputedPropertyName(methodSignature->name, genContext); - if (mlir::failed(result)) - { - return {"", false}; - } - - if (attr) - { - if (auto strAttr = dyn_cast(attr)) - { - return {strAttr.getValue().str(), true}; - } - else - { - llvm_unreachable("not implemented"); - } - } + const GenContext &genContext); - return {MLIRHelper::getName(methodSignature->name), true}; - } + std::tuple getNameForMethod(SignatureDeclarationBase methodSignature, const GenContext &genContext); mlir::LogicalResult getMethodNameOrPropertyName(bool isStaticClass, SignatureDeclarationBase methodSignature, std::string &methodName, - std::string &propertyName, const GenContext &genContext) - { - SyntaxKind kind = methodSignature; - if (kind == SyntaxKind::Constructor) - { - auto isStatic = isStaticClass || hasModifier(methodSignature, SyntaxKind::StaticKeyword); - if (isStatic) - { - methodName = std::string(STATIC_CONSTRUCTOR_NAME); - } - else - { - methodName = std::string(CONSTRUCTOR_NAME); - } - } - else if (kind == SyntaxKind::ConstructSignature) - { - methodName = std::string(NEW_CTOR_METHOD_NAME); - } - else if (kind == SyntaxKind::IndexSignature) - { - methodName = std::string(INDEX_ACCESS_FIELD_NAME); - } - else if (kind == SyntaxKind::CallSignature) - { - methodName = std::string(CALL_FIELD_NAME); - } - else if (kind == SyntaxKind::GetAccessor) - { - auto [name, result] = getNameForMethod(methodSignature, genContext); - if (!result) - { - return mlir::failure(); - } - - propertyName = name; - methodName = std::string("get_") + propertyName; - } - else if (kind == SyntaxKind::SetAccessor) - { - auto [name, result] = getNameForMethod(methodSignature, genContext); - if (!result) - { - return mlir::failure(); - } - - propertyName = name; - methodName = std::string("set_") + propertyName; - } - else - { - auto [name, result] = getNameForMethod(methodSignature, genContext); - if (!result) - { - return mlir::failure(); - } - - methodName = name; - } - - return mlir::success(); - } + std::string &propertyName, const GenContext &genContext); // RAII scope that redirects theModule and the builder into a fresh throwaway // module for the discovery pass. On scope exit the discovery module is erased diff --git a/tslang/lib/TypeScript/MLIRGenInterfaces.cpp b/tslang/lib/TypeScript/MLIRGenInterfaces.cpp new file mode 100644 index 00000000..9d40543d --- /dev/null +++ b/tslang/lib/TypeScript/MLIRGenInterfaces.cpp @@ -0,0 +1,859 @@ +// Interface and enum declaration code generation methods of MLIRGenImpl (see MLIRGenImpl.h). + +#include "MLIRGenImpl.h" + +namespace typescript +{ +namespace mlirgen +{ + + mlir::LogicalResult MLIRGenImpl::mlirGen(EnumDeclaration enumDeclarationAST, const GenContext &genContext) + { + auto namePtr = MLIRHelper::getName(enumDeclarationAST->name, stringAllocator); + if (namePtr.empty()) + { + return mlir::failure(); + } + + SymbolTableScopeT varScope(symbolTable); + + SmallVector enumLiteralTypes; + StringMap enumValues; + + auto appending = false; + if (getEnumsMap().contains(namePtr)) + { + auto dict = getEnumsMap().lookup(namePtr).second; + for (auto key : dict) + { + enumValues[key.getName()] = key.getValue(); + } + + appending = true; + } + else + { + getEnumsMap().insert( + { namePtr, { getEnumType().getElementType(), mlir::DictionaryAttr::get(builder.getContext(), {}) } }); + } + + auto &enumInfo = getEnumsMap()[namePtr]; + + auto activeBits = 32; + mlir::IntegerType::SignednessSemantics currentEnumValueSigedness = mlir::IntegerType::SignednessSemantics::Signless; + llvm::APInt currentEnumValue(32, 0); + for (auto enumMember : enumDeclarationAST->members) + { + auto location = loc(enumMember); + + auto memberNamePtr = MLIRHelper::getName(enumMember->name, stringAllocator); + if (memberNamePtr.empty()) + { + return mlir::failure(); + } + + mlir::Attribute enumValueAttr; + if (enumMember->initializer) + { + GenContext enumValueGenContext(genContext); + enumValueGenContext.allowConstEval = true; + auto result = mlirGen(enumMember->initializer, enumValueGenContext); + EXIT_IF_FAILED_OR_NO_VALUE(result) + auto enumValue = V(result); + + LLVM_DEBUG(llvm::dbgs() << "\n!! enum member: [ " << memberNamePtr << " ] = [ " << enumValue << " ]\n"); + + if (auto constOp = dyn_cast(enumValue.getDefiningOp())) + { + enumValueAttr = constOp.getValueAttr(); + if (auto intAttr = dyn_cast(enumValueAttr)) + { + if (intAttr.getType().isSignlessInteger()) + { + currentEnumValueSigedness = mlir::IntegerType::SignednessSemantics::Signless; + } + else if (intAttr.getType().isSignedInteger()) + { + currentEnumValueSigedness = mlir::IntegerType::SignednessSemantics::Signed; + } + else if (intAttr.getType().isUnsignedInteger()) + { + currentEnumValueSigedness = mlir::IntegerType::SignednessSemantics::Unsigned; + } + + currentEnumValue = intAttr.getValue(); + auto currentActiveBits = (int)intAttr.getValue().getActiveBits(); + if (currentActiveBits > activeBits) + { + activeBits = currentActiveBits; + } + } + } + else + { + emitError(loc(enumMember->initializer)) + << "enum member '" << memberNamePtr << "' must be constant"; + return mlir::failure(); + } + + enumLiteralTypes.push_back(enumValue.getType()); + + auto varDecl = std::make_shared(memberNamePtr, enumValue.getType(), location); + DECLARE(varDecl, enumValue); + + } + else + { + if (appending && currentEnumValue == 0 && stage == Stages::Discovering && !enumValues.contains(memberNamePtr)) + { + emitError(loc(enumMember)) + << "In an enum with multiple declarations, only one declaration can omit an initializer for its first enum element"; + return mlir::failure(); + } + + auto typeInt = mlir::IntegerType::get(builder.getContext(), activeBits, currentEnumValueSigedness); + enumValueAttr = builder.getIntegerAttr(typeInt, currentEnumValue); + auto indexType = mlir_ts::LiteralType::get(enumValueAttr, typeInt); + enumLiteralTypes.push_back(indexType); + + LLVM_DEBUG(llvm::dbgs() << "\n!! enum member: " << memberNamePtr << " <- " << indexType << "\n"); + + auto varDecl = std::make_shared(memberNamePtr, indexType, location); + auto enumVal = builder.create(location, indexType, enumValueAttr); + DECLARE(varDecl, enumVal); + } + + LLVM_DEBUG(llvm::dbgs() << "\n!! enum: " << namePtr << " value attr: " << enumValueAttr << "\n"); + + enumValues[memberNamePtr] = enumValueAttr; + + // update enum to support req. access + SmallVector namedEnumValues; + for (auto &key : enumValues) + { + namedEnumValues.push_back({builder.getStringAttr(key.first()), key.second}); + } + + enumInfo.second = mlir::DictionaryAttr::get(builder.getContext(), namedEnumValues /*adjustedEnumValues*/); + + currentEnumValue++; + } + + auto location = loc(enumDeclarationAST); + auto storeType = mth.getUnionTypeWithMerge(location, enumLiteralTypes); + + LLVM_DEBUG(llvm::dbgs() << "\n!! enum: " << namePtr << " storage type: " << storeType << "\n"); + + // update enum to support req. access + enumInfo.first = storeType; + + // register fullName for enum + auto fullNamePtr = getFullNamespaceName(namePtr); + + auto enumType = getEnumType( + mlir::FlatSymbolRefAttr::get(builder.getContext(), fullNamePtr), + enumInfo.first, + enumInfo.second); + + EnumInfo::TypePtr newEnumPtr; + if (fullNameEnumsMap.count(fullNamePtr)) + { + newEnumPtr = fullNameEnumsMap.lookup(fullNamePtr); + newEnumPtr->enumType = enumType; + } + else + { + // register class + newEnumPtr = std::make_shared(); + newEnumPtr->name = namePtr; + newEnumPtr->fullName = fullNamePtr; + newEnumPtr->elementNamespace = currentNamespace; + newEnumPtr->enumType = enumType; + fullNameEnumsMap.insert(fullNamePtr, newEnumPtr); + } + + if (getExportModifier(enumDeclarationAST)) + { + addEnumDeclarationToExport(namePtr, currentNamespace, enumType); + } + + return mlir::success(); + } + + ValueOrLogicalResult MLIRGenImpl::mlirGenCreateInterfaceVTableForObject(mlir::Location location, mlir::Value in, + mlir_ts::ObjectType objectType, InterfaceInfo::TypePtr newInterfacePtr, const GenContext &genContext) + { + auto fullObjectInterfaceVTableFieldName = interfaceVTableNameForObject(objectType, newInterfacePtr); + auto existValue = resolveFullNameIdentifier(location, fullObjectInterfaceVTableFieldName, true, genContext); + if (existValue) + { + return existValue; + } + + if (mlir::succeeded( + mlirGenObjectVirtualTableDefinitionForInterface(location, objectType, newInterfacePtr, genContext))) + { + auto globalVTableRefValue = resolveFullNameIdentifier(location, fullObjectInterfaceVTableFieldName, true, genContext); + + // we need to update methods references in VTable with functions from object; + if (newInterfacePtr->methods.size() > 0) { + + mlir_ts::TupleType storeType; + if (auto objectStoreType = dyn_cast(objectType.getStorageType())) + { + storeType = mlir_ts::TupleType::get(builder.getContext(), objectStoreType.getFields()); + } + else if (auto tupleType = dyn_cast(objectType.getStorageType())) + { + storeType = tupleType; + } + else + { + return mlir::failure(); + } + + // match VTable + // 1) clone vtable + auto vtableType = mlir::cast(mlir::cast(globalVTableRefValue.getType()).getElementType()); + auto valueVTable = builder.create(location, vtableType, globalVTableRefValue); + auto varVTable = builder.create(location, globalVTableRefValue.getType(), valueVTable, + builder.getBoolAttr(false), builder.getIndexAttr(0)); + + for (auto& method : newInterfacePtr->methods) + { + auto index = mth.getFieldIndexByFieldName(storeType, builder.getStringAttr(method.name)); + if (index == -1) + { + return mlir::failure(); + } + + auto fieldInfo = mth.getFieldInfoByIndex(storeType, index); + + auto methodRef = builder.create(location, mlir_ts::RefType::get(fieldInfo.type), in, index); + + LLVM_DEBUG(llvm::dbgs() << "\n!!\n\t vtable method: " << method.name + << "\n\t object method ref: " << V(methodRef) << "\n\n";); + + // where to save + auto fieldInfoVT = mth.getFieldInfoByIndex(vtableType, method.virtualIndex); + auto methodRefVT = builder.create(location, fieldInfoVT.type, varVTable, method.virtualIndex); + + LLVM_DEBUG(llvm::dbgs() << "\n!!\n\t vtable method: " << method.name + << "\n\t vtable method ref: " << V(methodRefVT) << "\n\n";); + + builder.create(location, methodRefVT, methodRef); + } + + // patched VTable + return V(varVTable); + } + + return globalVTableRefValue; + } + + return mlir::failure(); + } + + mlir::LogicalResult MLIRGenImpl::mlirGenObjectVirtualTableDefinitionForInterface(mlir::Location location, + mlir_ts::ObjectType objectType, + InterfaceInfo::TypePtr newInterfacePtr, + const GenContext &genContext) + { + + MLIRCodeLogic mcl(builder, compileOptions); + + auto storeType = objectType.getStorageType(); + + // TODO: should object accept only ObjectStorageType? + if (auto objectStoreType = dyn_cast(storeType)) + { + storeType = mlir_ts::TupleType::get(builder.getContext(), objectStoreType.getFields()); + } + + auto tupleStorageType = mlir::cast(mth.convertConstTupleTypeToTupleType(storeType)); + + SmallVector virtualTable; + auto result = getInterfaceVirtualTableForObject(location, tupleStorageType, newInterfacePtr, virtualTable); + if (mlir::failed(result)) + { + return result; + } + + // register global + auto fullClassInterfaceVTableFieldName = interfaceVTableNameForObject(objectType, newInterfacePtr); + registerVariable( + location, fullClassInterfaceVTableFieldName, true, VariableType::Var, + [&](mlir::Location location, const GenContext &genContext) { + // build vtable from names of methods + + auto virtTuple = getVirtualTableType(virtualTable); + + mlir::Value vtableValue = builder.create(location, virtTuple); + auto fieldIndex = 0; + for (auto methodOrField : virtualTable) + { + if (methodOrField.isField) + { + auto nullObj = builder.create(location, getNullType()); + if (!methodOrField.isMissing) + { + // TODO: test cast result + auto objectNull = cast(location, objectType, nullObj, genContext, true); + if (!objectNull) + { + return TypeValueInitType{mlir::Type(), mlir::Value(), TypeProvided::Yes}; + } + + auto fieldValue = mlirGenPropertyAccessExpression(location, objectNull, + methodOrField.fieldInfo.id, genContext); + assert(fieldValue); + if (!fieldValue) + { + return TypeValueInitType{mlir::Type(), mlir::Value(), TypeProvided::Yes}; + } + + auto fieldRef = mcl.GetReferenceFromValue(location, fieldValue); + + LLVM_DEBUG(llvm::dbgs() << "\n!!\n\t vtable field: " << methodOrField.fieldInfo.id + << "\n\t type: " << methodOrField.fieldInfo.type + << "\n\t provided data: " << fieldRef << "\n\n";); + + if (isa(fieldRef.getType())) + { + fieldRef = cast(location, mlir_ts::RefType::get(methodOrField.fieldInfo.type), fieldRef, + genContext); + } + else + { + assert(mlir::cast(fieldRef.getType()).getElementType() == + methodOrField.fieldInfo.type); + } + + // insert &(null)->field + vtableValue = builder.create( + location, virtTuple, fieldRef, vtableValue, + MLIRHelper::getStructIndex(builder, fieldIndex)); + } + else + { + // null value, as missing field/method + // auto nullObj = builder.create(location, getNullType()); + auto negative1 = builder.create(location, builder.getI64Type(), + mth.getI64AttrValue(-1)); + auto castedPtr = cast(location, mlir_ts::RefType::get(methodOrField.fieldInfo.type), + negative1, genContext); + vtableValue = builder.create( + location, virtTuple, castedPtr, vtableValue, + MLIRHelper::getStructIndex(builder, fieldIndex)); + } + } + else + { + llvm_unreachable("not implemented yet"); + /* + auto methodConstName = builder.create( + location, methodOrField.methodInfo.funcOp.getType(), + mlir::FlatSymbolRefAttr::get(builder.getContext(), + methodOrField.methodInfo.funcOp.getSymName())); + + vtableValue = + builder.create(location, virtTuple, methodConstName, vtableValue, + MLIRHelper::getStructIndex(rewriter, fieldIndex)); + */ + } + + fieldIndex++; + } + + return TypeValueInitType{virtTuple, vtableValue, TypeProvided::Yes}; + }, + genContext); + + return mlir::success(); + } + + mlir::LogicalResult MLIRGenImpl::registerGenericInterface(InterfaceDeclaration interfaceDeclarationAST, + const GenContext &genContext) + { + auto name = MLIRHelper::getName(interfaceDeclarationAST->name); + if (!name.empty()) + { + auto namePtr = StringRef(name).copy(stringAllocator); + auto fullNamePtr = getFullNamespaceName(namePtr); + if (fullNameGenericInterfacesMap.count(fullNamePtr)) + { + return mlir::success(); + } + + llvm::SmallVector typeParameters; + if (mlir::failed( + processTypeParameters(interfaceDeclarationAST->typeParameters, typeParameters, genContext))) + { + return mlir::failure(); + } + + GenericInterfaceInfo::TypePtr newGenericInterfacePtr = std::make_shared(); + newGenericInterfacePtr->name = namePtr; + newGenericInterfacePtr->fullName = fullNamePtr; + newGenericInterfacePtr->elementNamespace = currentNamespace; + newGenericInterfacePtr->typeParams = typeParameters; + newGenericInterfacePtr->interfaceDeclaration = interfaceDeclarationAST; + newGenericInterfacePtr->sourceFile = sourceFile; + newGenericInterfacePtr->fileName = mainSourceFileName; + + mlirGenInterfaceType(newGenericInterfacePtr, genContext); + + getGenericInterfacesMap().insert({namePtr, newGenericInterfacePtr}); + fullNameGenericInterfacesMap.insert(fullNamePtr, newGenericInterfacePtr); + + return mlir::success(); + } + + return mlir::failure(); + } + + InterfaceInfo::TypePtr MLIRGenImpl::mlirGenInterfaceInfo(InterfaceDeclaration interfaceDeclarationAST, bool &declareInterface, + const GenContext &genContext) + { + auto name = getNameWithArguments(interfaceDeclarationAST, genContext); + return mlirGenInterfaceInfo(name, declareInterface, genContext); + } + + InterfaceInfo::TypePtr MLIRGenImpl::mlirGenInterfaceInfo(const std::string &name, bool &declareInterface, + const GenContext &genContext) + { + declareInterface = false; + + auto namePtr = StringRef(name).copy(stringAllocator); + auto fullNamePtr = getFullNamespaceName(namePtr); + + InterfaceInfo::TypePtr newInterfacePtr; + if (fullNameInterfacesMap.count(fullNamePtr)) + { + newInterfacePtr = fullNameInterfacesMap.lookup(fullNamePtr); + getInterfacesMap().insert({namePtr, newInterfacePtr}); + declareInterface = !newInterfacePtr->interfaceType; + } + else + { + // register class + newInterfacePtr = std::make_shared(); + newInterfacePtr->name = namePtr; + newInterfacePtr->fullName = fullNamePtr; + newInterfacePtr->elementNamespace = currentNamespace; + + getInterfacesMap().insert({namePtr, newInterfacePtr}); + fullNameInterfacesMap.insert(fullNamePtr, newInterfacePtr); + declareInterface = true; + } + + if (declareInterface && mlir::succeeded(mlirGenInterfaceType(newInterfacePtr, genContext))) + { + newInterfacePtr->typeParamsWithArgs = genContext.typeParamsWithArgs; + } + + return newInterfacePtr; + } + + mlir::LogicalResult MLIRGenImpl::mlirGenInterfaceHeritageClauseExtends(InterfaceDeclaration interfaceDeclarationAST, + InterfaceInfo::TypePtr newInterfacePtr, + HeritageClause heritageClause, int &orderWeight, bool declareClass, + const GenContext &genContext) + { + if (heritageClause->token != SyntaxKind::ExtendsKeyword) + { + return mlir::success(); + } + + for (auto &extendsType : heritageClause->types) + { + auto result = mlirGen(extendsType, genContext); + EXIT_IF_FAILED(result); + auto ifaceType = V(result); + auto success = false; + mlir::TypeSwitch(ifaceType.getType()) + .template Case([&](auto interfaceType) { + auto interfaceInfo = getInterfaceInfoByFullName(interfaceType.getName().getValue()); + if (interfaceInfo) + { + newInterfacePtr->extends.push_back({-1, interfaceInfo}); + success = true; + } + }) + .template Case([&](auto tupleType) { + llvm::SmallVector destTupleFields; + if (mlir::succeeded(mth.getFields(tupleType, destTupleFields))) + { + orderWeight++; + success = true; + for (auto field : destTupleFields) + success &= mlir::succeeded( + mlirGenInterfaceAddFieldMember(newInterfacePtr, field.id, field.type, field.isConditional, orderWeight)); + } + }) + .Default([&](auto type) { llvm_unreachable("not implemented"); }); + + if (!success) + { + return mlir::failure(); + } + } + + return mlir::success(); + } + + mlir::LogicalResult MLIRGenImpl::mlirGen(InterfaceDeclaration interfaceDeclarationAST, const GenContext &genContext) + { + // do not proceed for Generic Interfaces for declaration + if (interfaceDeclarationAST->typeParameters.size() > 0 && genContext.typeParamsWithArgs.size() == 0) + { + return registerGenericInterface(interfaceDeclarationAST, genContext); + } + + auto declareInterface = false; + auto newInterfacePtr = mlirGenInterfaceInfo(interfaceDeclarationAST, declareInterface, genContext); + if (!newInterfacePtr) + { + return mlir::failure(); + } + + // do not process specialized interface second time; + if (!declareInterface && interfaceDeclarationAST->typeParameters.size() > 0 && + genContext.typeParamsWithArgs.size() > 0) + { + return mlir::success(); + } + + auto location = loc(interfaceDeclarationAST); + + auto ifaceGenContext = GenContext(genContext); + ifaceGenContext.thisType = newInterfacePtr->interfaceType; + + auto orderWeight = 0; + for (auto &heritageClause : interfaceDeclarationAST->heritageClauses) + { + if (mlir::failed(mlirGenInterfaceHeritageClauseExtends(interfaceDeclarationAST, newInterfacePtr, + heritageClause, orderWeight, declareInterface, genContext))) + { + return mlir::failure(); + } + } + + newInterfacePtr->recalcOffsets(); + + // clear all flags + for (auto &interfaceMember : interfaceDeclarationAST->members) + { + interfaceMember->processed = false; + } + + // add methods when we have classType + auto notResolved = 0; + do + { + auto lastTimeNotResolved = notResolved; + notResolved = 0; + + for (auto &interfaceMember : interfaceDeclarationAST->members) + { + orderWeight++; + if (mlir::failed(mlirGenInterfaceMethodMember( + interfaceDeclarationAST, newInterfacePtr, interfaceMember, orderWeight, declareInterface, ifaceGenContext))) + { + notResolved++; + } + } + + // repeat if not all resolved + if (lastTimeNotResolved > 0 && lastTimeNotResolved == notResolved) + { + // interface can depend on other interface declarations + // theModule.emitError("can't resolve dependencies in intrerface: ") << newInterfacePtr->name; + return mlir::failure(); + } + + } while (notResolved > 0); + + // add to export if any + if (auto hasExport = getExportModifier(interfaceDeclarationAST)) + { + addInterfaceDeclarationToExport(newInterfacePtr); + } + + return mlir::success(); + } + + mlir::LogicalResult MLIRGenImpl::mlirGenInterfaceAddFieldMember(InterfaceInfo::TypePtr newInterfacePtr, mlir::Attribute fieldId, mlir::Type typeIn, bool isConditional, int orderWeight, bool declareInterface) + { + auto &fieldInfos = newInterfacePtr->fields; + auto type = typeIn; + + // fix type for fields with FuncType + if (auto hybridFuncType = dyn_cast(type)) + { + + auto funcType = getFunctionType(hybridFuncType.getInputs(), hybridFuncType.getResults(), hybridFuncType.isVarArg()); + type = mth.getFunctionTypeAddingFirstArgType(funcType, getOpaqueType()); + } + else if (auto funcType = dyn_cast(type)) + { + + type = mth.getFunctionTypeAddingFirstArgType(funcType, getOpaqueType()); + } + + if (mth.isNoneType(type)) + { + LLVM_DEBUG(dbgs() << "\n!! interface field: " << fieldId << " FAILED\n"); + return mlir::failure(); + } + + auto fieldIndex = newInterfacePtr->getFieldIndex(fieldId); + if (fieldIndex == -1) + { + fieldInfos.push_back({fieldId, type, isConditional, orderWeight, newInterfacePtr->getNextVTableMemberIndex()}); + } + else + { + // update + fieldInfos[fieldIndex].type = type; + fieldInfos[fieldIndex].isConditional = isConditional; + } + + return mlir::success(); + } + + mlir::LogicalResult MLIRGenImpl::mlirGenInterfaceMethodMember(InterfaceDeclaration interfaceDeclarationAST, + InterfaceInfo::TypePtr newInterfacePtr, + TypeElement interfaceMember, int orderWeight, bool declareInterface, + const GenContext &genContext) + { + if (interfaceMember->processed) + { + return mlir::success(); + } + + auto location = loc(interfaceMember); + + auto &methodInfos = newInterfacePtr->methods; + + mlir::Value initValue; + mlir::Attribute fieldId; + mlir::Type type; + StringRef memberNamePtr; + + MLIRCodeLogic mcl(builder, compileOptions); + + SyntaxKind kind = interfaceMember; + if (kind == SyntaxKind::PropertySignature) + { + // property declaration + auto propertySignature = interfaceMember.as(); + auto isConditional = !!propertySignature->questionToken; + + fieldId = TupleFieldName(propertySignature->name, genContext); + + auto [type, init, typeProvided] = getTypeAndInit(propertySignature, genContext); + if (!type) + { + return mlir::failure(); + } + + if (mlir::failed(mlirGenInterfaceAddFieldMember(newInterfacePtr, fieldId, type, isConditional, orderWeight, declareInterface))) + { + return mlir::failure(); + } + } + else if (kind == SyntaxKind::MethodSignature + || kind == SyntaxKind::ConstructSignature || kind == SyntaxKind::CallSignature + || kind == SyntaxKind::GetAccessor || kind == SyntaxKind::SetAccessor) + { + auto methodSignature = interfaceMember.as(); + auto isConditional = !!methodSignature->questionToken; + + newInterfacePtr->hasNew |= kind == SyntaxKind::ConstructSignature; + // we need this code to add "THIS" param to declaration + interfaceMember->parent = interfaceDeclarationAST; + + std::string methodName; + std::string propertyName; + mlir_ts::FunctionType funcType; + if (mlir::failed(getInterfaceMethodNameAndType(location, newInterfacePtr->interfaceType, methodSignature, + methodName, propertyName, funcType, genContext))) + { + return mlir::failure(); + } + + if (mlir::failed(addInterfaceMethod(location, newInterfacePtr, methodInfos, + methodName, funcType, isConditional, orderWeight, declarationMode, genContext))) + { + return mlir::failure(); + } + + // add info about property + if (kind == SyntaxKind::GetAccessor || kind == SyntaxKind::SetAccessor) + { + auto accessor = newInterfacePtr->findAccessor(propertyName); + + auto &accessors = newInterfacePtr->accessors; + if (accessor == nullptr) + { + if (kind == SyntaxKind::GetAccessor) + { + accessors.push_back({funcType.getResult(0), propertyName, methodName, ""}); + } + else + { + accessors.push_back({funcType.getInputs().back(), propertyName, "", methodName}); + } + } + else + { + if (kind == SyntaxKind::GetAccessor) + { + accessor->getMethod = methodName; + } + else + { + accessor->setMethod = methodName; + } + } + } + + methodSignature->processed = true; + } + else if (kind == SyntaxKind::IndexSignature) + { + auto methodSignature = interfaceMember.as(); + // we need this code to add "THIS" param to declaration + interfaceMember->parent = interfaceDeclarationAST; + + std::string methodName; + std::string propertyName; + mlir_ts::FunctionType funcType; + if (mlir::failed(getInterfaceMethodNameAndType( + location, newInterfacePtr->interfaceType, methodSignature, methodName, propertyName, funcType, genContext))) + { + return mlir::failure(); + } + + // add get method + if (mlir::failed(addInterfaceMethod(location, newInterfacePtr, methodInfos, + INDEX_ACCESS_GET_FIELD_NAME, mth.getIndexGetFunctionType(funcType), true, orderWeight, declarationMode, genContext))) + { + return mlir::failure(); + } + + if (mlir::failed(addInterfaceMethod(location, newInterfacePtr, methodInfos, + INDEX_ACCESS_SET_FIELD_NAME, mth.getIndexSetFunctionType(funcType), true, orderWeight, declarationMode, genContext))) + { + return mlir::failure(); + } + + auto found = llvm::find_if(newInterfacePtr->indexes, [&] (auto indexInfo) { + return indexInfo.indexSignature == funcType; + }); + + if (found == newInterfacePtr->indexes.end()) + { + newInterfacePtr->indexes.push_back({funcType, INDEX_ACCESS_GET_FIELD_NAME, INDEX_ACCESS_SET_FIELD_NAME}); + } + + methodSignature->processed = true; + } + else + { + llvm_unreachable("not implemented"); + } + + return mlir::success(); + } + + std::tuple MLIRGenImpl::getNameForMethod(SignatureDeclarationBase methodSignature, const GenContext &genContext) + { + auto [attr, result] = getNameFromComputedPropertyName(methodSignature->name, genContext); + if (mlir::failed(result)) + { + return {"", false}; + } + + if (attr) + { + if (auto strAttr = dyn_cast(attr)) + { + return {strAttr.getValue().str(), true}; + } + else + { + llvm_unreachable("not implemented"); + } + } + + return {MLIRHelper::getName(methodSignature->name), true}; + } + + mlir::LogicalResult MLIRGenImpl::getMethodNameOrPropertyName(bool isStaticClass, SignatureDeclarationBase methodSignature, std::string &methodName, + std::string &propertyName, const GenContext &genContext) + { + SyntaxKind kind = methodSignature; + if (kind == SyntaxKind::Constructor) + { + auto isStatic = isStaticClass || hasModifier(methodSignature, SyntaxKind::StaticKeyword); + if (isStatic) + { + methodName = std::string(STATIC_CONSTRUCTOR_NAME); + } + else + { + methodName = std::string(CONSTRUCTOR_NAME); + } + } + else if (kind == SyntaxKind::ConstructSignature) + { + methodName = std::string(NEW_CTOR_METHOD_NAME); + } + else if (kind == SyntaxKind::IndexSignature) + { + methodName = std::string(INDEX_ACCESS_FIELD_NAME); + } + else if (kind == SyntaxKind::CallSignature) + { + methodName = std::string(CALL_FIELD_NAME); + } + else if (kind == SyntaxKind::GetAccessor) + { + auto [name, result] = getNameForMethod(methodSignature, genContext); + if (!result) + { + return mlir::failure(); + } + + propertyName = name; + methodName = std::string("get_") + propertyName; + } + else if (kind == SyntaxKind::SetAccessor) + { + auto [name, result] = getNameForMethod(methodSignature, genContext); + if (!result) + { + return mlir::failure(); + } + + propertyName = name; + methodName = std::string("set_") + propertyName; + } + else + { + auto [name, result] = getNameForMethod(methodSignature, genContext); + if (!result) + { + return mlir::failure(); + } + + methodName = name; + } + + return mlir::success(); + } + +} // namespace mlirgen +} // namespace typescript