diff --git a/tslang/lib/TypeScript/MLIRGenAccessCall.cpp b/tslang/lib/TypeScript/MLIRGenAccessCall.cpp index efe0cd3cd..c1051e2be 100644 --- a/tslang/lib/TypeScript/MLIRGenAccessCall.cpp +++ b/tslang/lib/TypeScript/MLIRGenAccessCall.cpp @@ -675,14 +675,14 @@ namespace mlirgen } - mlir::Value MLIRGenImpl::ClassIndexAccess(ClassInfo::TypePtr classInfo, - mlir::Location location, mlir::Value thisValue, mlir::Value argument, mlir_ts::AccessLevel accessingFromLevel, const GenContext &genContext) + mlir::Value MLIRGenImpl::ClassIndexAccess(ClassInfo::TypePtr classInfo, + mlir::Location location, mlir::Value thisValue, mlir::Value argument, bool isSuperClass, mlir_ts::AccessLevel accessingFromLevel, const GenContext &genContext) { if (classInfo->indexes.size() == 0) { emitError(location) << "indexer is not declared"; - return mlir::Value(); + return mlir::Value(); } auto indexInfo = classInfo->indexes.front(); @@ -709,8 +709,14 @@ namespace mlirgen // sync index CAST_A(result, location, argumentType, argument, genContext); + // same repair ClassMethodAccess/ClassAccessorAccess apply: `super[i]`'s + // thisValue is still the raw by-value ClassStorageType struct at this point, + // not a pointer - getThisRefOfClass detects that case and materializes it, + // same as it always did for `super.method()`/`super.`. + auto effectiveThisValue = getThisRefOfClass(location, classInfo->classType, thisValue, isSuperClass, genContext); + auto thisIndexAccessorOp = builder.create( - location, indexResultType, thisValue, V(result), + location, indexResultType, effectiveThisValue, V(result), getFunc ? mlir::FlatSymbolRefAttr::get(builder.getContext(), getFunc.name) : mlir::FlatSymbolRefAttr{}, setFunc ? mlir::FlatSymbolRefAttr::get(builder.getContext(), setFunc.name) @@ -781,7 +787,7 @@ namespace mlirgen { if (!classInfo->indexes.empty()) { - return ClassIndexAccess(classInfo, location, thisValue, argument, accessingFromLevel, genContext); + return ClassIndexAccess(classInfo, location, thisValue, argument, isSuperClass, accessingFromLevel, genContext); } } @@ -1013,8 +1019,16 @@ namespace mlirgen return mlirGenPropertyAccessExpression(location, expression, attr, isConditionalAccess, genContext); } - llvm_unreachable("not implemented (ElementAccessExpression)"); - } + // else access of index, e.g. `super[i]` - mirror the ClassType branch + // above: route through the ".index" property name so the resolver + // dispatches to ClassIndexAccess instead of falling off the end + // unimplemented. `super[i]` had no handling at all here before - it + // never even reached ClassIndexAccess, unlike `super.method()`/ + // `super.` which already went through the normal (string-name) + // branch above. + auto indexAccessor = builder.getStringAttr(INDEX_ACCESS_FIELD_NAME); + return mlirGenPropertyAccessExpression(location, expression, indexAccessor, isConditionalAccess, argumentExpression, genContext); + } else if (auto interfaceType = dyn_cast(arrayType)) { if (auto fieldName = argumentExpression.getDefiningOp()) diff --git a/tslang/lib/TypeScript/MLIRGenImpl.h b/tslang/lib/TypeScript/MLIRGenImpl.h index 1789e5115..e3b7cdf29 100644 --- a/tslang/lib/TypeScript/MLIRGenImpl.h +++ b/tslang/lib/TypeScript/MLIRGenImpl.h @@ -5527,9 +5527,8 @@ class MLIRGenImpl mlir::Location location, mlir::Value thisValue, int accessorIndex, bool isSuperClass, mlir_ts::AccessLevel accessingFromLevel, const GenContext &genContext); - // TODO: why isSuperClass is not used here? - mlir::Value ClassIndexAccess(ClassInfo::TypePtr classInfo, - mlir::Location location, mlir::Value thisValue, mlir::Value argument, mlir_ts::AccessLevel accessingFromLevel, const GenContext &genContext); + mlir::Value ClassIndexAccess(ClassInfo::TypePtr classInfo, + mlir::Location location, mlir::Value thisValue, mlir::Value argument, bool isSuperClass, mlir_ts::AccessLevel accessingFromLevel, const GenContext &genContext); mlir::Value ClassBaseClassAccess(ClassInfo::TypePtr classInfo, ClassInfo::TypePtr baseClass, int index, mlir::Location location, mlir::Value thisValue, StringRef name, mlir::Value argument, mlir_ts::AccessLevel accessingFromLevel, const GenContext &genContext); diff --git a/tslang/test/tester/CMakeLists.txt b/tslang/test/tester/CMakeLists.txt index 9d8a3f61f..9f9c04aa4 100644 --- a/tslang/test/tester/CMakeLists.txt +++ b/tslang/test/tester/CMakeLists.txt @@ -264,6 +264,7 @@ add_test(NAME test-compile-00-class-iterator COMMAND test-runner "${PROJECT_SOUR add_test(NAME test-compile-00-class-iterator-super COMMAND test-runner "${PROJECT_SOURCE_DIR}/test/tester/tests/00class_iterator_super.ts") add_test(NAME test-compile-00-class-symbol-iterator COMMAND test-runner "${PROJECT_SOURCE_DIR}/test/tester/tests/00class_symbol_iterator.ts") add_test(NAME test-compile-00-class-indexer COMMAND test-runner "${PROJECT_SOURCE_DIR}/test/tester/tests/00class_indexer.ts") +add_test(NAME test-compile-00-class-indexer-super COMMAND test-runner "${PROJECT_SOURCE_DIR}/test/tester/tests/00class_indexer_super.ts") add_test(NAME test-compile-00-class-from-tuple COMMAND test-runner "${PROJECT_SOURCE_DIR}/test/tester/tests/00class_from_tuple.ts") add_test(NAME test-compile-00-class-access-control COMMAND test-runner "${PROJECT_SOURCE_DIR}/test/tester/tests/00class_access_control.ts") add_test(NAME test-compile-00-class-protected-constructor COMMAND test-runner "${PROJECT_SOURCE_DIR}/test/tester/tests/00class_protected_constr.ts") @@ -626,6 +627,7 @@ add_test(NAME test-jit-00-class-iterator COMMAND test-runner -jit "${PROJECT_SOU add_test(NAME test-jit-00-class-iterator-super COMMAND test-runner -jit "${PROJECT_SOURCE_DIR}/test/tester/tests/00class_iterator_super.ts") add_test(NAME test-jit-00-class-symbol-iterator COMMAND test-runner -jit "${PROJECT_SOURCE_DIR}/test/tester/tests/00class_symbol_iterator.ts") add_test(NAME test-jit-00-class-indexer COMMAND test-runner -jit "${PROJECT_SOURCE_DIR}/test/tester/tests/00class_indexer.ts") +add_test(NAME test-jit-00-class-indexer-super COMMAND test-runner -jit "${PROJECT_SOURCE_DIR}/test/tester/tests/00class_indexer_super.ts") add_test(NAME test-jit-00-class-from-tuple COMMAND test-runner -jit "${PROJECT_SOURCE_DIR}/test/tester/tests/00class_from_tuple.ts") add_test(NAME test-jit-00-class-access-control COMMAND test-runner -jit "${PROJECT_SOURCE_DIR}/test/tester/tests/00class_access_control.ts") add_test(NAME test-jit-00-class-protected-constructor COMMAND test-runner -jit "${PROJECT_SOURCE_DIR}/test/tester/tests/00class_protected_constr.ts") diff --git a/tslang/test/tester/tests/00class_indexer_super.ts b/tslang/test/tester/tests/00class_indexer_super.ts new file mode 100644 index 000000000..18662782f --- /dev/null +++ b/tslang/test/tester/tests/00class_indexer_super.ts @@ -0,0 +1,39 @@ +class Storage { + #val: string = ""; + + [index: number]: string; + + get(index: number): string { + return this.#val; + } + + set(index: number, value: string) { + this.#val = value; + } +} + +// overriding an indexer and calling back into the base implementation via +// `super[index]` / `super[index] = value` - same crash class as +// `super.` (00class_accessor_super.ts, see the comment there): +// ClassIndexAccess never took an `isSuperClass` parameter at all (unlike +// ClassMethodAccess/ClassAccessorAccess), so `thisValue` was never repaired +// via getThisRefOfClass for `super[i]`. +class UpperStorage extends Storage { + [index: number]: string; + + get(index: number): string { + return super[index] + "!"; + } + + set(index: number, value: string) { + super[index] = "U:" + value; + } +} + +function main() { + const s = new UpperStorage(); + s[0] = "hi"; + assert(s[0] == "U:hi!"); + + print("done."); +}