Index: lib/CodeGen/CGBuiltin.cpp =================================================================== --- lib/CodeGen/CGBuiltin.cpp +++ lib/CodeGen/CGBuiltin.cpp @@ -1527,12 +1527,17 @@ case Builtin::BI__atomic_signal_fence: case Builtin::BI__c11_atomic_thread_fence: case Builtin::BI__c11_atomic_signal_fence: { - llvm::SynchronizationScope Scope; + unsigned Scope; + std::string ScopeName; if (BuiltinID == Builtin::BI__atomic_signal_fence || - BuiltinID == Builtin::BI__c11_atomic_signal_fence) - Scope = llvm::SingleThread; - else - Scope = llvm::CrossThread; + BuiltinID == Builtin::BI__c11_atomic_signal_fence) { + Scope = llvm::SynchScopeSingleThread; + ScopeName = "SingleThread"; + } else { + Scope = llvm::SynchScopeSystem; + ScopeName = "System"; + } + CGM.setSynchScopeMap(Scope, ScopeName); Value *Order = EmitScalarExpr(E->getArg(0)); if (isa(Order)) { int ord = cast(Order)->getZExtValue(); Index: lib/CodeGen/CodeGenModule.h =================================================================== --- lib/CodeGen/CodeGenModule.h +++ lib/CodeGen/CodeGenModule.h @@ -374,6 +374,9 @@ llvm::DenseMap AtomicSetterHelperFnMap; llvm::DenseMap AtomicGetterHelperFnMap; + /// \brief Mapping from synchronization scope to it's string representation. + std::map SynchScopeMap; + /// Map used to get unique type descriptor constants for sanitizers. llvm::DenseMap TypeDescriptorMap; @@ -582,6 +585,8 @@ AtomicGetterHelperFnMap[Ty] = Fn; } + void setSynchScopeMap(unsigned SynchScope, const std::string &SynchScopeName); + llvm::Constant *getTypeDescriptorFromMap(QualType Ty) { return TypeDescriptorMap[Ty]; } @@ -1233,6 +1238,9 @@ void EmitDeclMetadata(); + /// \brief Emit synchronization scope metadata. + void EmitSynchScopeMetadata(); + /// \brief Emit the Clang version as llvm.ident metadata. void EmitVersionIdentMetadata(); Index: lib/CodeGen/CodeGenModule.cpp =================================================================== --- lib/CodeGen/CodeGenModule.cpp +++ lib/CodeGen/CodeGenModule.cpp @@ -495,6 +495,8 @@ if (DebugInfo) DebugInfo->finalize(); + EmitSynchScopeMetadata(); + EmitVersionIdentMetadata(); EmitTargetMetadata(); @@ -4079,6 +4081,15 @@ return true; } +void CodeGenModule::setSynchScopeMap(unsigned SynchScope, + const std::string &SynchScopeName) { + auto Res = SynchScopeMap.find(SynchScope); + if (Res == SynchScopeMap.end()) + SynchScopeMap.insert(std::make_pair(SynchScope, SynchScopeName)); + else + assert(Res->second == SynchScopeName); +} + /// Emits metadata nodes associating all the global values in the /// current module with the Decls they came from. This is useful for /// projects using IR gen as a subroutine. @@ -4125,6 +4136,22 @@ } } +void CodeGenModule::EmitSynchScopeMetadata() { + if (!SynchScopeMap.size()) + return; + + llvm::LLVMContext &Ctx = TheModule.getContext(); + llvm::NamedMDNode *SynchScopeMetadata = + TheModule.getOrInsertNamedMetadata("synchscopes"); + for (auto &I : SynchScopeMap) { + llvm::Metadata *SynchScopeNode[2] = { + llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(Int32Ty, I.first)), + llvm::MDString::get(Ctx, I.second) + }; + SynchScopeMetadata->addOperand(llvm::MDNode::get(Ctx, SynchScopeNode)); + } +} + void CodeGenModule::EmitVersionIdentMetadata() { llvm::NamedMDNode *IdentMetadata = TheModule.getOrInsertNamedMetadata("llvm.ident"); Index: test/CodeGen/synchscopes.cpp =================================================================== --- test/CodeGen/synchscopes.cpp +++ test/CodeGen/synchscopes.cpp @@ -0,0 +1,17 @@ +// RUN: %clang -emit-llvm -S -std=c++11 %s -o - | FileCheck %s + +// CHECK: !synchscopes = !{!0, !1} +// CHECK: !0 = !{i32 0, !"System"} +// CHECK: !1 = !{i32 -1, !"SingleThread"} + +#include + +void synchscopes_acquire() { + atomic_thread_fence(std::memory_order_acquire); + atomic_signal_fence(std::memory_order_acquire); +} + +void synchscopes_release() { + atomic_thread_fence(std::memory_order_release); + atomic_signal_fence(std::memory_order_release); +}