diff --git a/tslang/include/TypeScript/MLIRLogic/MLIRGenStore.h b/tslang/include/TypeScript/MLIRLogic/MLIRGenStore.h index 92f0f0997..e306cc002 100644 --- a/tslang/include/TypeScript/MLIRLogic/MLIRGenStore.h +++ b/tslang/include/TypeScript/MLIRLogic/MLIRGenStore.h @@ -74,11 +74,11 @@ enum class Select: int struct VariableClass { - VariableClass() : type{VariableType::Const}, isExport{false}, isImport{false}, isDynamicImport{false}, isPublic{false}, isUsing{false}, isAppendingLinkage{false}, comdat{Select::NotSet}, isUsed{false}, atomic{false}, ordering{0}, syncscope{StringRef()}, isVolatile{false}, nonTemporal{false}, invariant{false} + VariableClass() : type{VariableType::Const}, isExport{false}, isImport{false}, isDynamicImport{false}, isPublic{false}, isUsing{false}, isAppendingLinkage{false}, comdat{Select::NotSet}, isUsed{false}, atomic{false}, ordering{0}, syncscope{StringRef()}, isVolatile{false}, nonTemporal{false}, invariant{false}, isBoxed{false} { } - VariableClass(VariableType type_) : type{type_}, isExport{false}, isImport{false}, isDynamicImport{false}, isPublic{false}, isUsing{false}, isAppendingLinkage{false}, comdat{Select::NotSet}, isUsed{false}, atomic{false}, ordering{0}, syncscope{StringRef()}, isVolatile{false}, nonTemporal{false}, invariant{false} + VariableClass(VariableType type_) : type{type_}, isExport{false}, isImport{false}, isDynamicImport{false}, isPublic{false}, isUsing{false}, isAppendingLinkage{false}, comdat{Select::NotSet}, isUsed{false}, atomic{false}, ordering{0}, syncscope{StringRef()}, isVolatile{false}, nonTemporal{false}, invariant{false}, isBoxed{false} { } @@ -97,6 +97,11 @@ struct VariableClass bool isVolatile; bool nonTemporal; bool invariant; + // @dllimport declaration-only marker: the exported symbol's storage is a + // single boxed pointer to the real data, not the data inline - see + // DeclarationPrinter.cpp's printVariableDeclaration and + // MLIRGenVariables.cpp's isDynamicImport load branch. + bool isBoxed; inline VariableClass& operator=(VariableType type_) { type = type_; return *this; } diff --git a/tslang/lib/TypeScript/DeclarationPrinter.cpp b/tslang/lib/TypeScript/DeclarationPrinter.cpp index afdbd0cbd..0bf9df4c7 100644 --- a/tslang/lib/TypeScript/DeclarationPrinter.cpp +++ b/tslang/lib/TypeScript/DeclarationPrinter.cpp @@ -306,6 +306,27 @@ namespace typescript printBeforeDeclaration(); + // no TS source syntax expresses "this symbol's storage is a single + // boxed pointer to the real data, not the data inline" - an inferred + // (untyped) object-literal export is boxed as ObjectType, but its + // structural-shape declaration text alone is indistinguishable from an + // explicitly-typed (unboxed, inline) export of the same shape. Emit a + // sibling @boxed decorator so the importer's isDynamicImport load + // (MLIRGenVariables.cpp, the branch that actually runs for every + // ordinary `import '...'` - see mlirGenImportSharedLib's '.' hack) + // knows to dereference one extra level instead of reading the tuple + // inline at the resolved symbol address. + if (auto objectType = dyn_cast(type)) + { + auto storageType = objectType.getStorageType(); + if (isa(storageType) || isa(storageType) || + isa(storageType)) + { + os << "@boxed"; + newline(); + } + } + os << (isConst ? "const" : "let") << " " << name << " : "; print(type); os << ";"; diff --git a/tslang/lib/TypeScript/MLIRGenVariables.cpp b/tslang/lib/TypeScript/MLIRGenVariables.cpp index 491edeadd..adada6b46 100644 --- a/tslang/lib/TypeScript/MLIRGenVariables.cpp +++ b/tslang/lib/TypeScript/MLIRGenVariables.cpp @@ -677,6 +677,24 @@ namespace mlirgen auto dllVarName = V(mlirGenStringValue(location, nameStr, true)); auto referenceToStaticFieldOpaque = builder.create( location, getOpaqueType(), dllVarName); + + if (varClass.isBoxed) + { + // the resolved symbol's storage is a single boxed + // pointer (ObjectType lowers to `ptr`) to the real + // data, not the data inline - load the pointer first, + // then load through it, instead of reading + // sizeof(fieldType) bytes directly at the symbol's own + // address (which would read past a lone 8-byte slot). + // See DeclarationPrinter.cpp's @boxed emission. + auto boxedType = getObjectType(fieldType); + auto refToBoxed = cast(location, mlir_ts::RefType::get(boxedType), referenceToStaticFieldOpaque, genContext); + auto boxedPtr = V(builder.create(location, boxedType, refToBoxed)); + auto refToTyped = V(cast(location, mlir_ts::RefType::get(fieldType), boxedPtr, genContext)); + auto valueOfField = builder.create(location, fieldType, refToTyped); + return std::make_tuple(valueOfField.getType(), V(valueOfField), TypeProvided::Yes); + } + auto refToTyped = cast(location, mlir_ts::RefType::get(fieldType), referenceToStaticFieldOpaque, genContext); auto valueOfField = builder.create(location, fieldType, refToTyped); return std::make_tuple(valueOfField.getType(), V(valueOfField), TypeProvided::Yes); @@ -766,6 +784,10 @@ namespace mlirgen } } + if (name == "boxed") { + varClass.isBoxed = true; + } + if (name == "used") { varClass.isUsed = true; } diff --git a/tslang/test/tester/CMakeLists.txt b/tslang/test/tester/CMakeLists.txt index d0143ffa3..b9b1df192 100644 --- a/tslang/test/tester/CMakeLists.txt +++ b/tslang/test/tester/CMakeLists.txt @@ -853,11 +853,7 @@ add_test(NAME test-compile-shared-decl-emit-class COMMAND test-runner -shared "$ add_test(NAME test-compile-shared-export-import-class-interface COMMAND test-runner -shared "${PROJECT_SOURCE_DIR}/test/tester/tests/import_class_interface.ts" "${PROJECT_SOURCE_DIR}/test/tester/tests/export_class_interface.ts") add_test(NAME test-compile-shared-export-import-object-literal-with-class-types COMMAND test-runner -shared "${PROJECT_SOURCE_DIR}/test/tester/tests/import_object_literal_with_class_types.ts" "${PROJECT_SOURCE_DIR}/test/tester/tests/export_object_literal_with_class_types.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") -# DISABLED: hangs (deadlock, not a crash - see docs/interface-vtable-simplification-design.md -# "Bug 1"). Direct field/method access on an imported untyped-export boxed global reaches a -# still-unfixed cross-module boxed-global initialization-ordering issue. Re-enable once fixed. 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") -set_tests_properties(test-compile-shared-export-import-object-literal-untyped PROPERTIES DISABLED TRUE) add_test(NAME test-compile-shared-export-import-object-literal-structural-typed COMMAND test-runner -shared -gctors-as-method "${PROJECT_SOURCE_DIR}/test/tester/tests/import_object_literal_structural_typed.ts" "${PROJECT_SOURCE_DIR}/test/tester/tests/export_object_literal_structural_typed.ts") add_test(NAME test-compile-shared-export-import-object-literal-structural-typed-params COMMAND test-runner -shared -gctors-as-method "${PROJECT_SOURCE_DIR}/test/tester/tests/import_object_literal_structural_typed_params.ts" "${PROJECT_SOURCE_DIR}/test/tester/tests/export_object_literal_structural_typed_params.ts") add_test(NAME test-compile-shared-export-import-vars COMMAND test-runner -shared "${PROJECT_SOURCE_DIR}/test/tester/tests/import_vars.ts" "${PROJECT_SOURCE_DIR}/test/tester/tests/export_vars.ts") @@ -875,9 +871,7 @@ add_test(NAME test-jit-shared-decl-emit-class COMMAND test-runner -jit -shared " add_test(NAME test-jit-shared-export-import-class-interface COMMAND test-runner -jit -shared "${PROJECT_SOURCE_DIR}/test/tester/tests/import_class_interface.ts" "${PROJECT_SOURCE_DIR}/test/tester/tests/export_class_interface.ts") add_test(NAME test-jit-shared-export-import-object-literal-with-class-types COMMAND test-runner -jit -shared "${PROJECT_SOURCE_DIR}/test/tester/tests/import_object_literal_with_class_types.ts" "${PROJECT_SOURCE_DIR}/test/tester/tests/export_object_literal_with_class_types.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") -# DISABLED: same known deadlock as the test-compile variant above. 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") -set_tests_properties(test-jit-shared-export-import-object-literal-untyped PROPERTIES DISABLED TRUE) add_test(NAME test-jit-shared-export-import-object-literal-structural-typed COMMAND test-runner -jit -shared -gctors-as-method "${PROJECT_SOURCE_DIR}/test/tester/tests/import_object_literal_structural_typed.ts" "${PROJECT_SOURCE_DIR}/test/tester/tests/export_object_literal_structural_typed.ts") add_test(NAME test-jit-shared-export-import-object-literal-structural-typed-params COMMAND test-runner -jit -shared -gctors-as-method "${PROJECT_SOURCE_DIR}/test/tester/tests/import_object_literal_structural_typed_params.ts" "${PROJECT_SOURCE_DIR}/test/tester/tests/export_object_literal_structural_typed_params.ts") add_test(NAME test-jit-shared-export-import-vars COMMAND test-runner -jit -shared "${PROJECT_SOURCE_DIR}/test/tester/tests/import_vars.ts" "${PROJECT_SOURCE_DIR}/test/tester/tests/export_vars.ts")