I was trying to compile lldb today using the latest clang for i686 and it failed at linking step due to undefined symbol __atomic_store
and I don’t have libatomic.
Upon closer look, the code which caused call __atomic_store
to be emitted is at lldb/source/Utility/Log.cpp:108
105 void Log::Disable(uint32_t flags) {
106 llvm::sys::ScopedWriter lock(m_mutex);
107
108 MaskType mask = m_mask.fetch_and(~flags, std::memory_order_relaxed);
109 if (!(mask & ~flags)) {
110 m_handler.reset();
111 m_channel.log_ptr.store(nullptr, std::memory_order_relaxed);
112 }
113 }
And the call to Disable()
is inlined into the following code.
203 void Log::Unregister(llvm::StringRef name) {
204 auto iter = g_channel_map->find(name);
205 assert(iter != g_channel_map->end());
206 iter->second.Disable(UINT32_MAX);
207 g_channel_map->erase(iter);
208 }
The MaskType
is uint64_t
so an 8-byte atomic operation is needed. The optimizer figures out that the anding with ~UINT32_MAX
will always result to 0 being written, so it’s turned into an atomic store operation. However the wrong alignment is emitted:
store atomic i64 0, ptr %20 monotonic, align 4
Which then results in a call to libatomic. The wrong alignment seems like a bug. If I force Log::Disable()
to be not inlined, then this problem goes away.