From e0d60e0911580ac18cbca7b5f61f7a8572a095af Mon Sep 17 00:00:00 2001 From: ASDAlexander77 Date: Sun, 12 Jul 2026 00:46:57 +0100 Subject: [PATCH] Update launch.json to correct DEFAULT_LIB_PATH for debug build --- tslang/lib/TypeScript/MLIRGen.cpp | 294 +++++++++++++++++++++--------- tslang/tslang/.vscode/launch.json | 4 +- 2 files changed, 206 insertions(+), 92 deletions(-) diff --git a/tslang/lib/TypeScript/MLIRGen.cpp b/tslang/lib/TypeScript/MLIRGen.cpp index e4d6213b..e2513a5a 100644 --- a/tslang/lib/TypeScript/MLIRGen.cpp +++ b/tslang/lib/TypeScript/MLIRGen.cpp @@ -21082,6 +21082,94 @@ genContext); LLVM_DEBUG(llvm::dbgs() << "\n!! cast " << valueType << "\n -> " << type << "\n";); + if (mlir::failed(verifyCastPreconditions(location, type, valueType, disableStrictNullCheck))) + { + return mlir::failure(); + } + + if (auto enumType = dyn_cast(valueType)) + { + value = builder.create(location, enumType.getElementType(), value); + valueType = value.getType(); + } + + if (auto result = castViaToPrimitive(location, type, value, valueType, genContext)) + { + return *result; + } + + if (auto result = castToStringSpecialCases(location, type, value, valueType, genContext)) + { + return *result; + } + + if (auto result = castToInterfaceSpecialCases(location, type, value, valueType, genContext)) + { + return *result; + } + + if (auto result = castTupleLikeVariants(location, type, value, valueType, genContext)) + { + return *result; + } + + if (auto result = castToOptionalType(location, type, value, valueType, genContext)) + { + return *result; + } + + if (auto result = castToTaggedUnionType(location, type, value, valueType, genContext)) + { + return *result; + } + + // const dest: cast via the unwrapped source type instead + if (auto constType = dyn_cast(type)) + { + // TODO: we can't convert array to const array + + auto currType = valueType; + if (auto refType = dyn_cast(currType)) + { + type = refType.getElementType(); + } + else if (auto tupleType = dyn_cast(currType)) + { + type = mth.convertTupleTypeToConstTupleType(tupleType); + } + else + { + return value; + } + } + + if (auto result = castFromSourceSpecialCases(location, type, value, valueType, genContext)) + { + return *result; + } + + if (mlir::failed(verifyFunctionCastRules(location, type, value, valueType, genContext))) + { + return mlir::failure(); + } + + if (auto result = castExtensionFunctionType(location, type, value, valueType)) + { + return *result; + } + + if (mlir::failed(verifyCastCompatibility(location, type, valueType))) + { + return mlir::failure(); + } + + return V(builder.create(location, type, value)); + } + + // cast() stages; each returns a value/failure when the case is handled or std::nullopt to continue the cast pipeline + + mlir::LogicalResult verifyCastPreconditions(mlir::Location location, mlir::Type type, mlir::Type valueType, bool disableStrictNullCheck) + { if (auto litType = dyn_cast(type)) { if (auto valLitType = dyn_cast(valueType)) @@ -21089,7 +21177,7 @@ genContext); if (litType.getValue() != valLitType.getValue()) { emitError(location, "can't cast from literal type: '") << valLitType.getValue() << "' to '" << litType.getValue() << "'"; - return mlir::failure(); + return mlir::failure(); } } } @@ -21118,25 +21206,23 @@ genContext); if (!hasNullOrAny) { emitError(location, "can't cast from 'null' to '") << to_print(type) << "' in 'strict null mode'"; - return mlir::failure(); + return mlir::failure(); } } } } - if (auto enumType = dyn_cast(valueType)) - { - value = builder.create(location, enumType.getElementType(), value); - valueType = value.getType(); - } + return mlir::success(); + } - // toPrimitive - if ((isa(type) - || isa(type) - || isa(type) - || isa(type) - || isa(type) - || isa(type) + std::optional castViaToPrimitive(mlir::Location location, mlir::Type type, mlir::Value value, mlir::Type valueType, const GenContext &genContext) + { + if ((isa(type) + || isa(type) + || isa(type) + || isa(type) + || isa(type) + || isa(type) || isa(type)) && (isa(valueType) || isa(valueType) @@ -21180,16 +21266,21 @@ genContext); auto callResultValue = V(callResult); if (isa(callResultValue.getType())) { - return V(builder.create(location, type, callResultValue)); + return V(builder.create(location, type, callResultValue)); } auto castValue = cast(location, type, callResultValue, genContext); EXIT_IF_FAILED_OR_NO_VALUE(castValue); return castValue; - } + } } - // class or array or tuple to string + return std::nullopt; + } + + // class or array or tuple to string + std::optional castToStringSpecialCases(mlir::Location location, mlir::Type type, mlir::Value value, mlir::Type valueType, const GenContext &genContext) + { if (auto stringType = dyn_cast(type)) { if (auto classType = dyn_cast(valueType)) @@ -21199,7 +21290,7 @@ genContext); { return res; } - + return mlirGenCallThisMethod(location, value, TO_STRING, undefined, undefined, genContext); } @@ -21225,7 +21316,7 @@ genContext); return mlirGenCallThisMethod(location, value, TO_STRING, undefined, undefined, genContext); } - return castTupleToString(location, value, mth.convertConstTupleTypeToTupleType(srcConstTupleType), + return castTupleToString(location, value, mth.convertConstTupleTypeToTupleType(srcConstTupleType), srcConstTupleType.getFields(), genContext); } else if (auto srcTupleType = dyn_cast(valueType)) @@ -21239,7 +21330,12 @@ genContext); } } - // to interface + return std::nullopt; + } + + // class or tuple or object to interface + std::optional castToInterfaceSpecialCases(mlir::Location location, mlir::Type type, mlir::Value value, mlir::Type valueType, const GenContext &genContext) + { if (auto interfaceType = dyn_cast(type)) { if (auto classType = dyn_cast(valueType)) @@ -21302,6 +21398,12 @@ genContext); } } + return std::nullopt; + } + + // casts between tuple-like types (tuple, const tuple, class storage, interface fields) + std::optional castTupleLikeVariants(mlir::Location location, mlir::Type type, mlir::Value value, mlir::Type valueType, const GenContext &genContext) + { // const tuple to tuple if (auto srcConstTupleType = dyn_cast(valueType)) { @@ -21318,14 +21420,14 @@ genContext); } else if (auto classType = dyn_cast(type)) { - fields = mlir::cast(classType.getStorageType()).getFields(); - return castTupleToClass(location, value, mth.convertConstTupleTypeToTupleType(srcConstTupleType), fields, classType, genContext); + fields = mlir::cast(classType.getStorageType()).getFields(); + return castTupleToClass(location, value, mth.convertConstTupleTypeToTupleType(srcConstTupleType), fields, classType, genContext); } else if (auto funcType = dyn_cast(type)) { emitError(location, "invalid cast from ") << to_print(valueType) << " to " << to_print(type); return mlir::failure(); - } + } } // tuple to tuple @@ -21351,7 +21453,7 @@ genContext); { emitError(location, "invalid cast from ") << to_print(valueType) << " to " << to_print(type); return mlir::failure(); - } + } } // class to tuple @@ -21386,16 +21488,21 @@ genContext); } else if (auto classType = dyn_cast(type)) { - fields = mlir::cast(classType.getStorageType()).getFields(); - return castFieldsToClass(location, value, fields, classType, genContext); - } + fields = mlir::cast(classType.getStorageType()).getFields(); + return castFieldsToClass(location, value, fields, classType, genContext); + } } - // optional - // TODO: it is in CastLogic as well, review usage and remove from here - // but if optional points to interface then it will not work - // example: from path.ts - // %6 = ts.Cast %4 : !ts.const_tuple<{"key",!ts.string},{"prev",!ts.undefined},{"typename",!ts.undefined}> to !ts.optional> + return std::nullopt; + } + + // optional + // TODO: it is in CastLogic as well, review usage and remove from here + // but if optional points to interface then it will not work + // example: from path.ts + // %6 = ts.Cast %4 : !ts.const_tuple<{"key",!ts.string},{"prev",!ts.undefined},{"typename",!ts.undefined}> to !ts.optional> + std::optional castToOptionalType(mlir::Location location, mlir::Type type, mlir::Value value, mlir::Type valueType, const GenContext &genContext) + { if (auto optType = dyn_cast(type)) { if (valueType == getUndefinedType()) @@ -21406,13 +21513,13 @@ genContext); { auto condValue = builder.create(location, getBooleanType(), value); return optionalValueOrUndefined( - location, - condValue, - [&](auto genContext) - { + location, + condValue, + [&](auto genContext) + { auto valueFromOptional = builder.create(location, optValueType.getElementType(), value); return cast(location, optType.getElementType(), valueFromOptional, genContext); - }, + }, genContext); } else @@ -21422,6 +21529,11 @@ genContext); } } + return std::nullopt; + } + + std::optional castToTaggedUnionType(mlir::Location location, mlir::Type type, mlir::Value value, mlir::Type valueType, const GenContext &genContext) + { if (auto unionType = dyn_cast(type)) { mlir::Type baseType; @@ -21436,36 +21548,23 @@ genContext); if (mth.canCastFromTo(location, valueType, subType)) { CAST(value, location, subType, value, genContext); - return V(builder.create(location, type, value)); + return V(builder.create(location, type, value)); } } } else { - return V(builder.create(location, type, value)); + return V(builder.create(location, type, value)); } } } - if (auto constType = dyn_cast(type)) - { - // TODO: we can't convert array to const array - - auto currType = valueType; - if (auto refType = dyn_cast(currType)) - { - type = refType.getElementType(); - } - else if (auto tupleType = dyn_cast(currType)) - { - type = mth.convertTupleTypeToConstTupleType(tupleType); - } - else - { - return value; - } - } + return std::nullopt; + } + // union or optional or any or opaque source type + std::optional castFromSourceSpecialCases(mlir::Location location, mlir::Type type, mlir::Value value, mlir::Type valueType, const GenContext &genContext) + { // union type to if (auto unionType = dyn_cast(valueType)) { @@ -21486,42 +21585,42 @@ genContext); if (isa(optType.getElementType())) { auto val = V(builder.create(location, optType.getElementType(), value)); - CAST_A(unwrappedValue, location, type, val, genContext); + CAST_A(unwrappedValue, location, type, val, genContext); return unwrappedValue; } // optional to value cast(when we change types) auto hasValue = builder.create(location, mlir_ts::BooleanType::get(builder.getContext()), value); - + MLIRCodeLogicHelper mclh(builder, location, compileOptions); - auto castedVal = mclh.conditionalValue(hasValue, - [&]() { + auto castedVal = mclh.conditionalValue(hasValue, + [&]() { auto optValue = builder.create(location, optType.getElementType(), value); - return cast(location, type, optValue, genContext); - }, + return cast(location, type, optValue, genContext); + }, [&](mlir::Type trueType) { if (mlir::isa(type)) { auto undefValue = builder.create(location, mlir_ts::UndefinedType::get(builder.getContext())); - return V(cast(location, type, undefValue, genContext)); + return V(cast(location, type, undefValue, genContext)); } if (auto destOptType = mlir::isa(type)) { auto destOptValue = builder.create(location, type); - return V(destOptValue); - } + return V(destOptValue); + } auto defValue = builder.create(location, type); - return V(defValue); + return V(defValue); }); - return castedVal; - } + return castedVal; + } // unboxing if (auto anyType = dyn_cast(valueType)) { - if (isa(type) + if (isa(type) || isa(type) || isa(type) || isa(type) @@ -21539,18 +21638,23 @@ genContext); if (auto funcType = dyn_cast(type)) { return V(builder.create(location, type, value)); - } + } if (auto hybridFuncType = dyn_cast(type)) { auto funcValue = builder.create( - location, - mlir_ts::FunctionType::get(builder.getContext(), hybridFuncType.getInputs(), hybridFuncType.getResults(), hybridFuncType.isVarArg()), + location, + mlir_ts::FunctionType::get(builder.getContext(), hybridFuncType.getInputs(), hybridFuncType.getResults(), hybridFuncType.isVarArg()), value); return V(builder.create(location, type, funcValue)); } } + return std::nullopt; + } + + mlir::LogicalResult verifyFunctionCastRules(mlir::Location location, mlir::Type type, mlir::Value value, mlir::Type valueType, const GenContext &genContext) + { if (mth.isAnyFunctionType(valueType) && mth.isAnyFunctionType(type)) { if (mth.isGenericType(valueType)) @@ -21564,7 +21668,7 @@ genContext); if (!mth.CanCastFunctionTypeToFunctionType(valueType, type)) { emitError(location, "invalid cast from ") << to_print(valueType) << " to " << to_print(type); - return mlir::failure(); + return mlir::failure(); } if (!mth.isGenericType(type) && !mth.isGenericType(valueType)) @@ -21579,7 +21683,12 @@ genContext); } } - // cast ext method to bound method + return mlir::success(); + } + + // cast ext method to bound method + std::optional castExtensionFunctionType(mlir::Location location, mlir::Type type, mlir::Value value, mlir::Type valueType) + { if (auto extFuncType = dyn_cast(valueType)) { if (auto hybridFuncType = dyn_cast(type)) @@ -21592,21 +21701,26 @@ genContext); { auto boundFunc = createBoundMethodFromExtensionMethod(location, value.getDefiningOp()); return V(builder.create(location, type, boundFunc)); - } + } } - // wrong casts - // TODO: put it into Cast::Verify - if (mth.isAnyFunctionType(valueType) && - !mth.isAnyFunctionType(type, true) - && !isa(type) + return std::nullopt; + } + + // wrong casts + // TODO: put it into Cast::Verify + mlir::LogicalResult verifyCastCompatibility(mlir::Location location, mlir::Type type, mlir::Type valueType) + { + if (mth.isAnyFunctionType(valueType) && + !mth.isAnyFunctionType(type, true) + && !isa(type) && !isa(type) && !isa(type)) { emitError(location, "invalid cast from ") << to_print(valueType) << " to " << to_print(type); return mlir::failure(); - } + } - if (isa(type) && isa(valueType) + if (isa(type) && isa(valueType) || isa(type) && isa(valueType)) { emitError(location, "invalid cast from ") << to_print(valueType) << " to " << to_print(type); @@ -21621,8 +21735,8 @@ genContext); auto extendsResult = mth.extendsType(location, valueArrayType.getElementType(), arrayType.getElementType(), typeParamsWithArgs); if (extendsResult != ExtendsResult::True) { - emitError(location, "invalid cast from ") << to_print(valueType) << " to " << to_print(type) - << " as element type " << to_print(arrayType.getElementType()) << " is not base of type " + emitError(location, "invalid cast from ") << to_print(valueType) << " to " << to_print(type) + << " as element type " << to_print(arrayType.getElementType()) << " is not base of type " << to_print(valueArrayType.getElementType()); return mlir::failure(); } @@ -21631,7 +21745,7 @@ genContext); if (isa(type) || isa(type)) { - if (isa(valueType) + if (isa(valueType) || isa(valueType) || isa(valueType) || isa(valueType) @@ -21641,11 +21755,11 @@ genContext); emitError(location, "invalid cast from ") << to_print(valueType) << " to " << to_print(type); return mlir::failure(); } - } + } if (isa(valueType) || isa(valueType)) { - if (isa(type) + if (isa(type) || isa(type) || isa(type) || isa(type)) @@ -21653,9 +21767,9 @@ genContext); emitError(location, "invalid cast from ") << to_print(valueType) << " to " << to_print(type); return mlir::failure(); } - } + } - return V(builder.create(location, type, value)); + return mlir::success(); } ValueOrLogicalResult castPrimitiveTypeFromAny(mlir::Location location, mlir::Type type, mlir::Value value, const GenContext &genContext) diff --git a/tslang/tslang/.vscode/launch.json b/tslang/tslang/.vscode/launch.json index 5496c514..81b30496 100644 --- a/tslang/tslang/.vscode/launch.json +++ b/tslang/tslang/.vscode/launch.json @@ -469,7 +469,7 @@ "environment": [ { "name": "DEFAULT_LIB_PATH", - "value": "${workspaceFolder}/../../../TypeScriptCompilerDefaultLib/__build/debug" + "value": "${workspaceFolder}/../../../TypeScriptCompilerDefaultLib/__build" }, { "name": "GC_LIB_PATH", @@ -498,7 +498,7 @@ "excludedModules": [ "DoNotLookForThisOne*.dll" ] } } - }, + }, { "name": "(Windows) tslang.exe - EXE(OPT) - NO DEFAULT", "type": "cppvsdbg",