diff --git a/tslang/lib/TypeScript/MLIRGenImpl.h b/tslang/lib/TypeScript/MLIRGenImpl.h index 63aac409e..1c01ddf16 100644 --- a/tslang/lib/TypeScript/MLIRGenImpl.h +++ b/tslang/lib/TypeScript/MLIRGenImpl.h @@ -60,6 +60,7 @@ #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/SourceMgr.h" #include "llvm/Support/Path.h" +#include "llvm/Support/FileSystem.h" #include "llvm/Support/Error.h" #include "llvm/Support/raw_ostream.h" //#include "llvm/IR/DebugInfoMetadata.h" @@ -13899,6 +13900,11 @@ class MLIRGenImpl } // The file an `import` of a local source module names: next to the main file, `.ts` added. + // Without an extension, the module's file for the target comes first: `import "./m"` is m.win32.ts + // on Windows, m.linux.ts on Linux and Android, m..ts elsewhere, when it + // exists, else m.ts. A module with code per target (the vtables and layouts of a C++ ABI, say) + // is then picked as the default library picks lib.win32.ts or lib.linux.ts, while the importer + // names one module. std::string includeFilePath(StringRef fileName) { SmallString<256> fileNameStr(fileName); @@ -13910,11 +13916,6 @@ class MLIRGenImpl fileNameStr.append(subStr); } - if (sys::path::extension(fileName) == "") - { - fileNameStr += ".ts"; - } - SmallString<256> fullPath; if (!sys::path::has_root_path(fileNameStr)) { @@ -13924,9 +13925,40 @@ class MLIRGenImpl } sys::path::append(fullPath, fileNameStr); + + if (sys::path::extension(fileName) == "") + { + SmallString<256> targetPath(fullPath); + targetPath += "."; + targetPath += targetOSFileSuffix(); + targetPath += ".ts"; + if (sys::fs::exists(targetPath)) + { + return targetPath.str().str(); + } + + fullPath += ".ts"; + } + return fullPath.str().str(); } + // The OS part of a module's file name for the target (includeFilePath): win32, linux (Android + // too, as the default library builds lib.linux.ts for it), or the target triple's OS name. + StringRef targetOSFileSuffix() + { + llvm::Triple triple(compileOptions.moduleTargetTriple); + switch (triple.getOS()) + { + case llvm::Triple::Win32: + return "win32"; + case llvm::Triple::Linux: + return "linux"; + default: + return llvm::Triple::getOSTypeName(triple.getOS()); + } + } + std::pair> loadIncludeFile(mlir::Location location, StringRef fullPath) { std::string ignored; diff --git a/tslang/test/tester/CMakeLists.txt b/tslang/test/tester/CMakeLists.txt index e8302c4b6..11694dce5 100644 --- a/tslang/test/tester/CMakeLists.txt +++ b/tslang/test/tester/CMakeLists.txt @@ -1340,6 +1340,27 @@ tslang_add_test(NAME test-compile-export-import-owned-returns COMMAND test-runne tslang_add_test(NAME test-compile-export-import-const-locals COMMAND test-runner "${PROJECT_SOURCE_DIR}/test/tester/tests/import_const_locals.ts" "${PROJECT_SOURCE_DIR}/test/tester/tests/export_const_locals.ts") tslang_add_test(NAME test-compile-export-import-const-functions COMMAND test-runner "${PROJECT_SOURCE_DIR}/test/tester/tests/import_const_functions.ts" "${PROJECT_SOURCE_DIR}/test/tester/tests/export_const_functions.ts") tslang_add_test(NAME test-compile-export-import-generators COMMAND test-runner "${PROJECT_SOURCE_DIR}/test/tester/tests/import_generators.ts" "${PROJECT_SOURCE_DIR}/test/tester/tests/export_generators.ts") +# `import './export_os_suffix'` takes the target's file, export_os_suffix.win32.ts or +# export_os_suffix.linux.ts: the host's is compiled and linked beside it, and the import's +# declarations for each target are those of its file (the OS function that file declares). +if (WIN32) + tslang_add_test(NAME test-compile-export-import-os-suffix COMMAND test-runner "${PROJECT_SOURCE_DIR}/test/tester/tests/import_os_suffix.ts" "${PROJECT_SOURCE_DIR}/test/tester/tests/export_os_suffix.win32.ts") +elseif (CMAKE_SYSTEM_NAME STREQUAL "Linux") + tslang_add_test(NAME test-compile-export-import-os-suffix COMMAND test-runner "${PROJECT_SOURCE_DIR}/test/tester/tests/import_os_suffix.ts" "${PROJECT_SOURCE_DIR}/test/tester/tests/export_os_suffix.linux.ts") +endif() +foreach(os_suffix "win32|x86_64-pc-windows-msvc|GetCurrentProcessId|getpid" "linux|x86_64-unknown-linux-gnu|getpid|GetCurrentProcessId") + string(REPLACE "|" ";" os_suffix "${os_suffix}") + list(GET os_suffix 0 os_name) + list(GET os_suffix 1 os_triple) + list(GET os_suffix 2 os_function) + list(GET os_suffix 3 os_other_function) + add_test(NAME test-compile-import-os-suffix-${os_name} + COMMAND $ --emit=mlir --no-default-lib -mtriple=${os_triple} + "${PROJECT_SOURCE_DIR}/test/tester/tests/import_os_suffix.ts") + set_tests_properties(test-compile-import-os-suffix-${os_name} + PROPERTIES PASS_REGULAR_EXPRESSION "ts\\.Func @${os_function} " + FAIL_REGULAR_EXPRESSION "ts\\.Func @${os_other_function} |error:") +endforeach() tslang_add_test(NAME test-compile-rc-export-import-owned-returns COMMAND test-runner -mm=rc "${PROJECT_SOURCE_DIR}/test/tester/tests/import_owned_returns.ts" "${PROJECT_SOURCE_DIR}/test/tester/tests/export_owned_returns.ts") tslang_add_test(NAME test-compile-none-export-import-owned-returns COMMAND test-runner -mm=none "${PROJECT_SOURCE_DIR}/test/tester/tests/import_owned_returns.ts" "${PROJECT_SOURCE_DIR}/test/tester/tests/export_owned_returns.ts") tslang_add_test(NAME test-compile-export-import-class-extends COMMAND test-runner "${PROJECT_SOURCE_DIR}/test/tester/tests/import_class_extends.ts" "${PROJECT_SOURCE_DIR}/test/tester/tests/export_class_extends.ts") diff --git a/tslang/test/tester/tests/export_os_suffix.linux.ts b/tslang/test/tester/tests/export_os_suffix.linux.ts new file mode 100644 index 000000000..3288a7819 --- /dev/null +++ b/tslang/test/tester/tests/export_os_suffix.linux.ts @@ -0,0 +1,13 @@ +// The Linux file of the module `import './export_os_suffix'` names (import_os_suffix.ts): an +// import without an extension takes .win32.ts on Windows, .linux.ts on Linux. + +declare function getpid(): s32; + +namespace O { + + export const osFile = "linux"; + + export function processId(): u32 { + return getpid(); + } +} diff --git a/tslang/test/tester/tests/export_os_suffix.win32.ts b/tslang/test/tester/tests/export_os_suffix.win32.ts new file mode 100644 index 000000000..6da3ecbbf --- /dev/null +++ b/tslang/test/tester/tests/export_os_suffix.win32.ts @@ -0,0 +1,13 @@ +// The Windows file of the module `import './export_os_suffix'` names (import_os_suffix.ts): an +// import without an extension takes .win32.ts on Windows, .linux.ts on Linux. + +declare function GetCurrentProcessId(): u32; + +namespace O { + + export const osFile = "win32"; + + export function processId(): u32 { + return GetCurrentProcessId(); + } +} diff --git a/tslang/test/tester/tests/import_os_suffix.ts b/tslang/test/tester/tests/import_os_suffix.ts new file mode 100644 index 000000000..d6e2f65f3 --- /dev/null +++ b/tslang/test/tester/tests/import_os_suffix.ts @@ -0,0 +1,12 @@ +import './export_os_suffix' + +// There is no export_os_suffix.ts: the import takes the target's file, export_os_suffix.win32.ts or +// export_os_suffix.linux.ts, the one compiled and linked beside this (the other one's functions +// would be missing at link time). + +function main() { + assert(O.osFile == "win32" || O.osFile == "linux", "the module's file for the target"); + assert(O.processId() != 0, "and its functions"); + + print("done."); +}