From fe2a0e90ca8024686e0d48329b725ebc997d222b Mon Sep 17 00:00:00 2001 From: ASDAlexander77 Date: Wed, 22 Jul 2026 21:08:23 +0100 Subject: [PATCH] Implement printAccessor method and update tests for class accessors --- .../MLIRLogic/MLIRDeclarationPrinter.h | 1 + tslang/lib/TypeScript/DeclarationPrinter.cpp | 73 +++++++++++++++++++ tslang/lib/TypeScript/MLIRGenAccessCall.cpp | 72 ++++++++++++++++++ tslang/test/tester/CMakeLists.txt | 16 ++-- 4 files changed, 154 insertions(+), 8 deletions(-) diff --git a/tslang/include/TypeScript/MLIRLogic/MLIRDeclarationPrinter.h b/tslang/include/TypeScript/MLIRLogic/MLIRDeclarationPrinter.h index 57eb7a8b6..986d8b274 100644 --- a/tslang/include/TypeScript/MLIRLogic/MLIRDeclarationPrinter.h +++ b/tslang/include/TypeScript/MLIRLogic/MLIRDeclarationPrinter.h @@ -35,6 +35,7 @@ namespace typescript void printParams(ArrayRef, mlir::Type); void printFunction(StringRef, ArrayRef, mlir::Type); void printMethod(bool, StringRef, ArrayRef, mlir::Type, mlir::Type); + void printAccessor(bool, StringRef, StringRef, mlir_ts::AccessLevel, ArrayRef, mlir::Type, mlir::Type); void printNamespaceBegin(NamespaceInfo::TypePtr); void printNamespaceEnd(NamespaceInfo::TypePtr); void print(mlir::Type); diff --git a/tslang/lib/TypeScript/DeclarationPrinter.cpp b/tslang/lib/TypeScript/DeclarationPrinter.cpp index 128fe681b..cde0e14bc 100644 --- a/tslang/lib/TypeScript/DeclarationPrinter.cpp +++ b/tslang/lib/TypeScript/DeclarationPrinter.cpp @@ -255,6 +255,38 @@ namespace typescript } } + void MLIRDeclarationPrinter::printAccessor(bool isStatic, StringRef keyword, StringRef name, mlir_ts::AccessLevel accessLevel, + ArrayRef params, mlir::Type returnType, mlir::Type thisType) + { + os.indent(4); + + if (accessLevel == mlir_ts::AccessLevel::Protected) + { + os << "protected "; + } + else if (accessLevel == mlir_ts::AccessLevel::Private) + { + os << "private "; + } + + if (isStatic) + { + os << "static "; + } + + os << keyword << " " << name; + + printParams(params, thisType); + + if (returnType) + { + os << " : "; + print(returnType); + } + + newline(); + } + void MLIRDeclarationPrinter::printTypeDeclaration(StringRef name, NamespaceInfo::TypePtr elementNamespace, mlir::Type type) { printNamespaceBegin(elementNamespace); @@ -467,6 +499,22 @@ namespace typescript if (filterName(method.name)) continue; + // get/set accessors are ALSO registered here under their mangled + // "get_x"/"set_x" funcOp name (so same-file/JIT compiles can find them as + // ordinary methods) - but that mangled form is printed separately below, + // via classType->accessors, using real `get`/`set` syntax. Printing it + // again here as a plain method would make the importer register it as an + // ordinary MethodDeclaration instead of a GetAccessor/SetAccessor, so + // property-style access (`obj.x`, `super.x`) would never populate the + // reconstructed class's accessors list and fail to resolve. + if (llvm::any_of(classType->accessors, [&](auto &accessor) { + return (accessor.get && accessor.get.name == method.funcName) || + (accessor.set && accessor.set.name == method.funcName); + })) + { + continue; + } + os.indent(4); if (method.accessLevel == mlir_ts::AccessLevel::Protected) @@ -488,6 +536,31 @@ namespace typescript newline(); } + // accessors + for (auto accessor : classType->accessors) + { + if (filterName(accessor.name)) + continue; + + if (accessor.get) + { + printAccessor( + accessor.isStatic, "get", accessor.name, accessor.getAccessLevel, + accessor.get.funcType.getParams(), + accessor.get.funcType.getNumResults() > 0 ? accessor.get.funcType.getResult(0) : mlir::Type(), + classType->classType); + } + + if (accessor.set) + { + printAccessor( + accessor.isStatic, "set", accessor.name, accessor.setAccessLevel, + accessor.set.funcType.getParams(), + mlir::Type(), + classType->classType); + } + } + // TODO: we can't declare generic methods, otherwise we need to declare body of methods // generic methods // for (auto method : classType->staticGenericMethods) diff --git a/tslang/lib/TypeScript/MLIRGenAccessCall.cpp b/tslang/lib/TypeScript/MLIRGenAccessCall.cpp index 6f722380e..efe0cd3cd 100644 --- a/tslang/lib/TypeScript/MLIRGenAccessCall.cpp +++ b/tslang/lib/TypeScript/MLIRGenAccessCall.cpp @@ -591,6 +591,78 @@ namespace mlirgen else { auto effectiveThisValue = getThisRefOfClass(location, classInfo->classType, thisValue, isSuperClass, genContext); + + if (classInfo->isDynamicImport) + { + // A plain FlatSymbolRefAttr (the path below) lowers to a call the static linker + // must resolve - but a -shared importer never links against the exporter's .lib + // (see cross-module-instanceof-investigation.md), so it needs the same runtime + // resolution ClassMethodAccess already does for dynamic-import members: resolve + // each accessor function to a VALUE (direct ref / dlsym-style global / inline + // SearchForAddressOfSymbolOp) and drive the call through the "indirect" + // (function-pointer) accessor op instead of the symbol-attr one. + auto resolveAccessorFunc = [&](FunctionEntry funcEntry) -> mlir::Value { + if (!funcEntry) + { + return mlir::Value(); + } + + StringRef funcName = funcEntry.name; + auto effectiveFuncType = funcEntry.funcType; + + if (auto funcOp = theModule.lookupSymbol(funcName)) + { + if (!funcOp.getBody().empty()) + { + return builder.create( + location, effectiveFuncType, mlir::FlatSymbolRefAttr::get(builder.getContext(), funcName)); + } + } + + auto globalFuncVar = resolveFullNameIdentifier(location, funcName, false, genContext); + if (!globalFuncVar) + { + auto symbolNameValue = V(mlirGenStringValue(location, funcName.str(), true)); + auto referenceToFuncOpaque = builder.create( + location, getOpaqueType(), symbolNameValue); + auto castResult = cast(location, effectiveFuncType, referenceToFuncOpaque, genContext); + if (castResult.failed_or_no_value()) + { + emitError(location, "Class member '") << funcName << "' can't be resolved (dynamic import)"; + return mlir::Value(); + } + + globalFuncVar = V(castResult); + } + + return globalFuncVar; + }; + + auto getterValue = resolveAccessorFunc(getFunc); + auto setterValue = resolveAccessorFunc(setFunc); + if ((getFunc && !getterValue) || (setFunc && !setterValue)) + { + return mlir::Value(); + } + + auto opaqueThisType = mlir_ts::OpaqueType::get(builder.getContext()); + if (!getterValue) + { + getterValue = builder.create( + location, mlir_ts::FunctionType::get(builder.getContext(), {opaqueThisType}, {accessorResultType}, false)); + } + + if (!setterValue) + { + setterValue = builder.create( + location, mlir_ts::FunctionType::get(builder.getContext(), {opaqueThisType, accessorResultType}, {}, false)); + } + + auto thisIndirectAccessorOp = builder.create( + location, accessorResultType, effectiveThisValue, getterValue, setterValue, mlir::Value()); + return thisIndirectAccessorOp.getResult(0); + } + auto thisAccessorOp = builder.create( location, accessorResultType, effectiveThisValue, getFunc ? mlir::FlatSymbolRefAttr::get(builder.getContext(), getFunc.name) diff --git a/tslang/test/tester/CMakeLists.txt b/tslang/test/tester/CMakeLists.txt index 0ed5578bd..9d8a3f61f 100644 --- a/tslang/test/tester/CMakeLists.txt +++ b/tslang/test/tester/CMakeLists.txt @@ -951,12 +951,12 @@ add_test(NAME test-compile-shared-export-import-class-structural-interface COMMA # add_test(NAME test-compile-shared-export-import-class-implements-interface-abstract COMMAND test-runner -shared "${PROJECT_SOURCE_DIR}/test/tester/tests/import_class_implements_interface_abstract.ts" "${PROJECT_SOURCE_DIR}/test/tester/tests/export_class_implements_interface_abstract.ts") # FIXED: see the matching test-compile-export-import-class-generic comment above (2026-07-22). add_test(NAME test-compile-shared-export-import-class-generic COMMAND test-runner -shared "${PROJECT_SOURCE_DIR}/test/tester/tests/import_class_generic.ts" "${PROJECT_SOURCE_DIR}/test/tester/tests/export_class_generic.ts") -# DISABLED: known issue found 2026-07-22 (separate from the super-accessor-call crash fixed -# above). Under the -shared dynamic-import path, a base class's get/set accessors are not -# resolvable at all from a derived class in another module ("Class member 'celsius' can't be -# found") - the same class of gap as the disabled generic-class tests: declaration -# reconstruction for a dynamically-imported class is incomplete for some member kinds. -# add_test(NAME test-compile-shared-export-import-class-accessor COMMAND test-runner -shared "${PROJECT_SOURCE_DIR}/test/tester/tests/import_class_accessor.ts" "${PROJECT_SOURCE_DIR}/test/tester/tests/export_class_accessor.ts") +# FIXED (2026-07-22): the -shared declaration-reconstruction path never printed real +# get/set syntax for a class's accessors, only the underlying get_x/set_x funcOps as +# ordinary methods - so property-style access ("Class member 'celsius' can't be found") +# never populated the reimported class's accessors list. See print(ClassInfo::TypePtr) +# in DeclarationPrinter.cpp. +add_test(NAME test-compile-shared-export-import-class-accessor COMMAND test-runner -shared "${PROJECT_SOURCE_DIR}/test/tester/tests/import_class_accessor.ts" "${PROJECT_SOURCE_DIR}/test/tester/tests/export_class_accessor.ts") add_test(NAME test-compile-shared-export-import-object-literal-with-interface COMMAND test-runner -shared -gctors-as-method "${PROJECT_SOURCE_DIR}/test/tester/tests/import_object_literal_with_interface.ts" "${PROJECT_SOURCE_DIR}/test/tester/tests/export_object_literal_with_interface.ts") add_test(NAME test-compile-shared-export-import-object-literal-untyped COMMAND test-runner -shared -gctors-as-method "${PROJECT_SOURCE_DIR}/test/tester/tests/import_object_literal_untyped.ts" "${PROJECT_SOURCE_DIR}/test/tester/tests/export_object_literal_untyped.ts") add_test(NAME test-compile-shared-export-import-object-literal-untyped-multi-method COMMAND test-runner -shared -gctors-as-method "${PROJECT_SOURCE_DIR}/test/tester/tests/import_object_literal_untyped_multi_method.ts" "${PROJECT_SOURCE_DIR}/test/tester/tests/export_object_literal_untyped_multi_method.ts") @@ -995,8 +995,8 @@ add_test(NAME test-jit-shared-export-import-class-structural-interface COMMAND t # add_test(NAME test-jit-shared-export-import-class-implements-interface-abstract COMMAND test-runner -jit -shared "${PROJECT_SOURCE_DIR}/test/tester/tests/import_class_implements_interface_abstract.ts" "${PROJECT_SOURCE_DIR}/test/tester/tests/export_class_implements_interface_abstract.ts") # FIXED: see the matching test-compile-export-import-class-generic comment above (2026-07-22). add_test(NAME test-jit-shared-export-import-class-generic COMMAND test-runner -jit -shared "${PROJECT_SOURCE_DIR}/test/tester/tests/import_class_generic.ts" "${PROJECT_SOURCE_DIR}/test/tester/tests/export_class_generic.ts") -# DISABLED: see the matching test-compile-shared-export-import-class-accessor comment above (known issue, 2026-07-22). -# add_test(NAME test-jit-shared-export-import-class-accessor COMMAND test-runner -jit -shared "${PROJECT_SOURCE_DIR}/test/tester/tests/import_class_accessor.ts" "${PROJECT_SOURCE_DIR}/test/tester/tests/export_class_accessor.ts") +# FIXED: see the matching test-compile-shared-export-import-class-accessor comment above (2026-07-22). +add_test(NAME test-jit-shared-export-import-class-accessor COMMAND test-runner -jit -shared "${PROJECT_SOURCE_DIR}/test/tester/tests/import_class_accessor.ts" "${PROJECT_SOURCE_DIR}/test/tester/tests/export_class_accessor.ts") add_test(NAME test-jit-shared-export-import-object-literal-with-interface COMMAND test-runner -jit -shared -gctors-as-method "${PROJECT_SOURCE_DIR}/test/tester/tests/import_object_literal_with_interface.ts" "${PROJECT_SOURCE_DIR}/test/tester/tests/export_object_literal_with_interface.ts") add_test(NAME test-jit-shared-export-import-object-literal-untyped COMMAND test-runner -jit -shared -gctors-as-method "${PROJECT_SOURCE_DIR}/test/tester/tests/import_object_literal_untyped.ts" "${PROJECT_SOURCE_DIR}/test/tester/tests/export_object_literal_untyped.ts") add_test(NAME test-jit-shared-export-import-object-literal-untyped-multi-method COMMAND test-runner -jit -shared -gctors-as-method "${PROJECT_SOURCE_DIR}/test/tester/tests/import_object_literal_untyped_multi_method.ts" "${PROJECT_SOURCE_DIR}/test/tester/tests/export_object_literal_untyped_multi_method.ts")