StringAttr's StorageUniquer not being initialized on MacOS

I’ve updated a project to a more recent LLVM codebase and now I’m having a weird problem on my MacOS machine. I initially thought it was an M1-compatibility issue, but I managed to test on an older Macbook with Intel processor and the problem shows up also there.
Also, it does crash only with LLVM built in release / release with debug info modes. When LLVM is built in debug mode, the parser works perfectly.
The problem doesn’t show in Linux.

When my dialect is loaded, it seems like the storage uniquer for the StringAttr is not initialized. I’ve managed to reduce the test case to a minimum, but I don’t get if there’s a bug inside MLIR or if I missed something.

LLVM commit: cfeacec833f25cfb3ea52eec4e0a9930e3194d3f

Source code: https://github.com/mscuttari/mlir-macos-crash

Test file:

test.test

Stack trace:

LLVM ERROR: can't create Attribute 'mlir::StringAttr' because storage uniquer isn't initialized: the dialect was likely not loaded, or the attribute wasn't added with addAttributes<...>() in the Dialect::initialize() method.
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.
Stack dump:
0.	Program arguments: <path_to_test_file>
Stack dump without symbol names (ensure you have llvm-symbolizer in your PATH or set the environment var `LLVM_SYMBOLIZER_PATH` to point to it):
0  libLLVM.dylib            0x0000000111ae3c68 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) + 56
1  libLLVM.dylib            0x0000000111ae2e30 llvm::sys::RunSignalHandlers() + 112
2  libLLVM.dylib            0x0000000111ae42b0 SignalHandler(int) + 304
3  libsystem_platform.dylib 0x000000019fd674a4 _sigtramp + 56
4  libsystem_pthread.dylib  0x000000019fd4fee0 pthread_kill + 288
5  libsystem_c.dylib        0x000000019fc8a340 abort + 168
6  libLLVM.dylib            0x0000000111a2aef0 llvm::report_fatal_error(llvm::Twine const&, bool) + 472
7  libMLIRTest.dylib        0x0000000103c7d4ac bool llvm::function_ref<bool (mlir::StorageUniquer::BaseStorage const*)>::callback_fn<mlir::detail::StringAttrStorage* mlir::StorageUniquer::get<mlir::detail::StringAttrStorage, llvm::StringRef&, mlir::NoneType&>(llvm::function_ref<void (mlir::detail::StringAttrStorage*)>, mlir::TypeID, llvm::StringRef&, mlir::NoneType&)::'lambda'(mlir::StorageUniquer::BaseStorage const*)>(long, mlir::StorageUniquer::BaseStorage const*) + 0
8  libMLIRTest.dylib        0x0000000103c5c3d8 mlir::StringAttr::get(mlir::MLIRContext*, llvm::Twine const&) + 316
9  libMLIRTest.dylib        0x0000000103cd048c mlir::RegisteredOperationName::insert(llvm::StringRef, mlir::Dialect&, mlir::TypeID, llvm::unique_function<mlir::ParseResult (mlir::OpAsmParser&, mlir::OperationState&) const>&&, llvm::unique_function<void (mlir::Operation*, mlir::OpAsmPrinter&, llvm::StringRef) const>&&, llvm::unique_function<mlir::LogicalResult (mlir::Operation*) const>&&, llvm::unique_function<mlir::LogicalResult (mlir::Operation*) const>&&, llvm::unique_function<mlir::LogicalResult (mlir::Operation*, llvm::ArrayRef<mlir::Attribute>, llvm::SmallVectorImpl<mlir::OpFoldResult>&) const>&&, llvm::unique_function<void (mlir::RewritePatternSet&, mlir::MLIRContext*) const>&&, mlir::detail::InterfaceMap&&, llvm::unique_function<bool (mlir::TypeID) const>&&, llvm::ArrayRef<llvm::StringRef>) + 384
10 libMLIRTest.dylib        0x0000000103c27998 void mlir::RegisteredOperationName::insert<mlir::test::TestOp>(mlir::Dialect&) + 280
11 libMLIRTest.dylib        0x0000000103c274d8 void mlir::Dialect::addOperations<mlir::test::TestOp>() + 52
12 libMLIRTest.dylib        0x0000000103c273dc mlir::test::TestDialect::initialize() + 24
13 libMLIRTest.dylib        0x0000000103c27360 mlir::test::TestDialect::TestDialect(mlir::MLIRContext*) + 124
14 libMLIRTest.dylib        0x0000000103c2740c mlir::test::TestDialect::TestDialect(mlir::MLIRContext*) + 36
15 test-opt                 0x0000000102ff6e64 mlir::test::TestDialect* mlir::MLIRContext::getOrLoadDialect<mlir::test::TestDialect>()::'lambda'()::operator()() const + 56
16 test-opt                 0x0000000102ff6e0c std::__1::unique_ptr<mlir::Dialect, std::__1::default_delete<mlir::Dialect>> llvm::function_ref<std::__1::unique_ptr<mlir::Dialect, std::__1::default_delete<mlir::Dialect>> ()>::callback_fn<mlir::test::TestDialect* mlir::MLIRContext::getOrLoadDialect<mlir::test::TestDialect>()::'lambda'()>(long) + 40
17 test-opt                 0x0000000103093be0 mlir::MLIRContext::getOrLoadDialect(llvm::StringRef, mlir::TypeID, llvm::function_ref<std::__1::unique_ptr<mlir::Dialect, std::__1::default_delete<mlir::Dialect>> ()>) + 428
18 test-opt                 0x0000000102ff6d60 mlir::test::TestDialect* mlir::MLIRContext::getOrLoadDialect<mlir::test::TestDialect>() + 108
19 test-opt                 0x0000000102ff6ce8 void mlir::DialectRegistry::insert<mlir::test::TestDialect>()::'lambda'(mlir::MLIRContext*)::operator()(mlir::MLIRContext*) const + 28
20 test-opt                 0x0000000102ff6cac decltype(static_cast<void mlir::DialectRegistry::insert<mlir::test::TestDialect>()::'lambda'(mlir::MLIRContext*)&>(fp)(static_cast<mlir::MLIRContext*>(fp0))) std::__1::__invoke<void mlir::DialectRegistry::insert<mlir::test::TestDialect>()::'lambda'(mlir::MLIRContext*)&, mlir::MLIRContext*>(void mlir::DialectRegistry::insert<mlir::test::TestDialect>()::'lambda'(mlir::MLIRContext*)&, mlir::MLIRContext*&&) + 36
21 test-opt                 0x0000000102ff6c58 mlir::Dialect* std::__1::__invoke_void_return_wrapper<mlir::Dialect*, false>::__call<void mlir::DialectRegistry::insert<mlir::test::TestDialect>()::'lambda'(mlir::MLIRContext*)&, mlir::MLIRContext*>(void mlir::DialectRegistry::insert<mlir::test::TestDialect>()::'lambda'(mlir::MLIRContext*)&, mlir::MLIRContext*&&) + 52
22 test-opt                 0x0000000102ff6c04 std::__1::__function::__alloc_func<void mlir::DialectRegistry::insert<mlir::test::TestDialect>()::'lambda'(mlir::MLIRContext*), std::__1::allocator<void mlir::DialectRegistry::insert<mlir::test::TestDialect>()::'lambda'(mlir::MLIRContext*)>, mlir::Dialect* (mlir::MLIRContext*)>::operator()(mlir::MLIRContext*&&) + 52
23 test-opt                 0x0000000102ff5784 std::__1::__function::__func<void mlir::DialectRegistry::insert<mlir::test::TestDialect>()::'lambda'(mlir::MLIRContext*), std::__1::allocator<void mlir::DialectRegistry::insert<mlir::test::TestDialect>()::'lambda'(mlir::MLIRContext*)>, mlir::Dialect* (mlir::MLIRContext*)>::operator()(mlir::MLIRContext*&&) + 52
24 test-opt                 0x000000010305f4a4 mlir::Dialect* llvm::function_ref<mlir::Dialect* (mlir::MLIRContext*)>::callback_fn<std::__1::function<mlir::Dialect* (mlir::MLIRContext*)> const>(long, mlir::MLIRContext*) + 40
25 test-opt                 0x0000000103093a18 mlir::MLIRContext::getOrLoadDialect(llvm::StringRef) + 172
26 test-opt                 0x00000001030ec228 (anonymous namespace)::OperationParser::parseCustomOperationName() + 720
27 test-opt                 0x00000001030e9650 (anonymous namespace)::OperationParser::parseOperation() + 416
28 test-opt                 0x00000001030e8450 mlir::parseSourceFile(llvm::SourceMgr const&, mlir::Block*, mlir::MLIRContext*, mlir::LocationAttr*, mlir::AsmParserState*) + 664
29 test-opt                 0x00000001030bbf3c performActions(llvm::raw_ostream&, bool, bool, llvm::SourceMgr&, mlir::MLIRContext*, llvm::function_ref<mlir::LogicalResult (mlir::PassManager&)>) + 284
30 test-opt                 0x00000001030ba934 processBuffer(llvm::raw_ostream&, std::__1::unique_ptr<llvm::MemoryBuffer, std::__1::default_delete<llvm::MemoryBuffer>>, bool, bool, bool, bool, llvm::function_ref<mlir::LogicalResult (mlir::PassManager&)>, mlir::DialectRegistry&, llvm::ThreadPool*) + 552
31 test-opt                 0x00000001030ba6c4 mlir::MlirOptMain(llvm::raw_ostream&, std::__1::unique_ptr<llvm::MemoryBuffer, std::__1::default_delete<llvm::MemoryBuffer>>, llvm::function_ref<mlir::LogicalResult (mlir::PassManager&)>, mlir::DialectRegistry&, bool, bool, bool, bool, bool) + 284
32 test-opt                 0x00000001030bb30c mlir::MlirOptMain(int, char**, llvm::StringRef, mlir::DialectRegistry&, bool) + 2172
33 test-opt                 0x0000000102ff3ff0 main + 116
34 dyld                     0x000000010377d08c start + 520

I think building MLIR with dylibs on MacOS isn’t well supported still, we only likely support static builds. Not that we wouldn’t want to do it, but we haven’t had bandwidth / someone invested enough time into it.

Just tried with a static build and it worked, very thanks for the fast answer. If I can give a suggestion, I think it would very useful to have, somewhere in the documentation, a short list of the current supported build configurations, so that once progress is made one can simply check that instead of trying to understand the current status.

Also, sounds like another instance of the dreaded: MLIR TypeID mechanism is incompatible with cross-DSO/DLL usage · Issue #52621 · llvm/llvm-project · GitHub