Skip to content

Commit fe2a0e9

Browse files
Implement printAccessor method and update tests for class accessors
1 parent bb27386 commit fe2a0e9

4 files changed

Lines changed: 154 additions & 8 deletions

File tree

tslang/include/TypeScript/MLIRLogic/MLIRDeclarationPrinter.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ namespace typescript
3535
void printParams(ArrayRef<mlir::Type>, mlir::Type);
3636
void printFunction(StringRef, ArrayRef<mlir::Type>, mlir::Type);
3737
void printMethod(bool, StringRef, ArrayRef<mlir::Type>, mlir::Type, mlir::Type);
38+
void printAccessor(bool, StringRef, StringRef, mlir_ts::AccessLevel, ArrayRef<mlir::Type>, mlir::Type, mlir::Type);
3839
void printNamespaceBegin(NamespaceInfo::TypePtr);
3940
void printNamespaceEnd(NamespaceInfo::TypePtr);
4041
void print(mlir::Type);

tslang/lib/TypeScript/DeclarationPrinter.cpp

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,38 @@ namespace typescript
255255
}
256256
}
257257

258+
void MLIRDeclarationPrinter::printAccessor(bool isStatic, StringRef keyword, StringRef name, mlir_ts::AccessLevel accessLevel,
259+
ArrayRef<mlir::Type> params, mlir::Type returnType, mlir::Type thisType)
260+
{
261+
os.indent(4);
262+
263+
if (accessLevel == mlir_ts::AccessLevel::Protected)
264+
{
265+
os << "protected ";
266+
}
267+
else if (accessLevel == mlir_ts::AccessLevel::Private)
268+
{
269+
os << "private ";
270+
}
271+
272+
if (isStatic)
273+
{
274+
os << "static ";
275+
}
276+
277+
os << keyword << " " << name;
278+
279+
printParams(params, thisType);
280+
281+
if (returnType)
282+
{
283+
os << " : ";
284+
print(returnType);
285+
}
286+
287+
newline();
288+
}
289+
258290
void MLIRDeclarationPrinter::printTypeDeclaration(StringRef name, NamespaceInfo::TypePtr elementNamespace, mlir::Type type)
259291
{
260292
printNamespaceBegin(elementNamespace);
@@ -467,6 +499,22 @@ namespace typescript
467499
if (filterName(method.name))
468500
continue;
469501

502+
// get/set accessors are ALSO registered here under their mangled
503+
// "get_x"/"set_x" funcOp name (so same-file/JIT compiles can find them as
504+
// ordinary methods) - but that mangled form is printed separately below,
505+
// via classType->accessors, using real `get`/`set` syntax. Printing it
506+
// again here as a plain method would make the importer register it as an
507+
// ordinary MethodDeclaration instead of a GetAccessor/SetAccessor, so
508+
// property-style access (`obj.x`, `super.x`) would never populate the
509+
// reconstructed class's accessors list and fail to resolve.
510+
if (llvm::any_of(classType->accessors, [&](auto &accessor) {
511+
return (accessor.get && accessor.get.name == method.funcName) ||
512+
(accessor.set && accessor.set.name == method.funcName);
513+
}))
514+
{
515+
continue;
516+
}
517+
470518
os.indent(4);
471519

472520
if (method.accessLevel == mlir_ts::AccessLevel::Protected)
@@ -488,6 +536,31 @@ namespace typescript
488536
newline();
489537
}
490538

539+
// accessors
540+
for (auto accessor : classType->accessors)
541+
{
542+
if (filterName(accessor.name))
543+
continue;
544+
545+
if (accessor.get)
546+
{
547+
printAccessor(
548+
accessor.isStatic, "get", accessor.name, accessor.getAccessLevel,
549+
accessor.get.funcType.getParams(),
550+
accessor.get.funcType.getNumResults() > 0 ? accessor.get.funcType.getResult(0) : mlir::Type(),
551+
classType->classType);
552+
}
553+
554+
if (accessor.set)
555+
{
556+
printAccessor(
557+
accessor.isStatic, "set", accessor.name, accessor.setAccessLevel,
558+
accessor.set.funcType.getParams(),
559+
mlir::Type(),
560+
classType->classType);
561+
}
562+
}
563+
491564
// TODO: we can't declare generic methods, otherwise we need to declare body of methods
492565
// generic methods
493566
// for (auto method : classType->staticGenericMethods)

tslang/lib/TypeScript/MLIRGenAccessCall.cpp

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -591,6 +591,78 @@ namespace mlirgen
591591
else
592592
{
593593
auto effectiveThisValue = getThisRefOfClass(location, classInfo->classType, thisValue, isSuperClass, genContext);
594+
595+
if (classInfo->isDynamicImport)
596+
{
597+
// A plain FlatSymbolRefAttr (the path below) lowers to a call the static linker
598+
// must resolve - but a -shared importer never links against the exporter's .lib
599+
// (see cross-module-instanceof-investigation.md), so it needs the same runtime
600+
// resolution ClassMethodAccess already does for dynamic-import members: resolve
601+
// each accessor function to a VALUE (direct ref / dlsym-style global / inline
602+
// SearchForAddressOfSymbolOp) and drive the call through the "indirect"
603+
// (function-pointer) accessor op instead of the symbol-attr one.
604+
auto resolveAccessorFunc = [&](FunctionEntry funcEntry) -> mlir::Value {
605+
if (!funcEntry)
606+
{
607+
return mlir::Value();
608+
}
609+
610+
StringRef funcName = funcEntry.name;
611+
auto effectiveFuncType = funcEntry.funcType;
612+
613+
if (auto funcOp = theModule.lookupSymbol<mlir_ts::FuncOp>(funcName))
614+
{
615+
if (!funcOp.getBody().empty())
616+
{
617+
return builder.create<mlir_ts::SymbolRefOp>(
618+
location, effectiveFuncType, mlir::FlatSymbolRefAttr::get(builder.getContext(), funcName));
619+
}
620+
}
621+
622+
auto globalFuncVar = resolveFullNameIdentifier(location, funcName, false, genContext);
623+
if (!globalFuncVar)
624+
{
625+
auto symbolNameValue = V(mlirGenStringValue(location, funcName.str(), true));
626+
auto referenceToFuncOpaque = builder.create<mlir_ts::SearchForAddressOfSymbolOp>(
627+
location, getOpaqueType(), symbolNameValue);
628+
auto castResult = cast(location, effectiveFuncType, referenceToFuncOpaque, genContext);
629+
if (castResult.failed_or_no_value())
630+
{
631+
emitError(location, "Class member '") << funcName << "' can't be resolved (dynamic import)";
632+
return mlir::Value();
633+
}
634+
635+
globalFuncVar = V(castResult);
636+
}
637+
638+
return globalFuncVar;
639+
};
640+
641+
auto getterValue = resolveAccessorFunc(getFunc);
642+
auto setterValue = resolveAccessorFunc(setFunc);
643+
if ((getFunc && !getterValue) || (setFunc && !setterValue))
644+
{
645+
return mlir::Value();
646+
}
647+
648+
auto opaqueThisType = mlir_ts::OpaqueType::get(builder.getContext());
649+
if (!getterValue)
650+
{
651+
getterValue = builder.create<mlir_ts::UndefOp>(
652+
location, mlir_ts::FunctionType::get(builder.getContext(), {opaqueThisType}, {accessorResultType}, false));
653+
}
654+
655+
if (!setterValue)
656+
{
657+
setterValue = builder.create<mlir_ts::UndefOp>(
658+
location, mlir_ts::FunctionType::get(builder.getContext(), {opaqueThisType, accessorResultType}, {}, false));
659+
}
660+
661+
auto thisIndirectAccessorOp = builder.create<mlir_ts::ThisIndirectAccessorOp>(
662+
location, accessorResultType, effectiveThisValue, getterValue, setterValue, mlir::Value());
663+
return thisIndirectAccessorOp.getResult(0);
664+
}
665+
594666
auto thisAccessorOp = builder.create<mlir_ts::ThisAccessorOp>(
595667
location, accessorResultType, effectiveThisValue,
596668
getFunc ? mlir::FlatSymbolRefAttr::get(builder.getContext(), getFunc.name)

tslang/test/tester/CMakeLists.txt

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -951,12 +951,12 @@ add_test(NAME test-compile-shared-export-import-class-structural-interface COMMA
951951
# 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")
952952
# FIXED: see the matching test-compile-export-import-class-generic comment above (2026-07-22).
953953
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")
954-
# DISABLED: known issue found 2026-07-22 (separate from the super-accessor-call crash fixed
955-
# above). Under the -shared dynamic-import path, a base class's get/set accessors are not
956-
# resolvable at all from a derived class in another module ("Class member 'celsius' can't be
957-
# found") - the same class of gap as the disabled generic-class tests: declaration
958-
# reconstruction for a dynamically-imported class is incomplete for some member kinds.
959-
# 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")
954+
# FIXED (2026-07-22): the -shared declaration-reconstruction path never printed real
955+
# get/set syntax for a class's accessors, only the underlying get_x/set_x funcOps as
956+
# ordinary methods - so property-style access ("Class member 'celsius' can't be found")
957+
# never populated the reimported class's accessors list. See print(ClassInfo::TypePtr)
958+
# in DeclarationPrinter.cpp.
959+
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")
960960
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")
961961
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")
962962
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
995995
# 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")
996996
# FIXED: see the matching test-compile-export-import-class-generic comment above (2026-07-22).
997997
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")
998-
# DISABLED: see the matching test-compile-shared-export-import-class-accessor comment above (known issue, 2026-07-22).
999-
# 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")
998+
# FIXED: see the matching test-compile-shared-export-import-class-accessor comment above (2026-07-22).
999+
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")
10001000
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")
10011001
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")
10021002
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")

0 commit comments

Comments
 (0)