Index: lib/CodeGen/CGStmt.cpp |
diff --git a/lib/CodeGen/CGStmt.cpp b/lib/CodeGen/CGStmt.cpp |
index 5e2ebe0d9cd4656e9278c6a172513dc09ed0d77f..e9e1f014f1b55905004e0f4cd19c2d2c46d13b91 100644 |
--- a/lib/CodeGen/CGStmt.cpp |
+++ b/lib/CodeGen/CGStmt.cpp |
@@ -1701,6 +1701,31 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) { |
Result->addAttribute(llvm::AttributeSet::FunctionIndex, |
llvm::Attribute::NoUnwind); |
+ // @LOCALMOD-START |
+ // For PNaCl, emit two compiler fences containing a sequentially |
+ // consistent fence (just like __sync_synchronize). This should |
+ // enforce ordering of more than just atomic memory accesses, though |
+ // it won't guarantee that all accesses (e.g. those to non-escaping |
+ // objects) will not be reordered. |
+ bool isEmptyAsm = AsmString.empty(); |
+ // Different triples will encode "touch everything" differently, e.g.: |
+ // - le32-unknown-nacl has "~{memory}". |
+ // - x86 "~{memory},~{dirflag},~{fpsr},~{flags}". |
+ // The following code therefore only searches for memory: this pass |
+ // deals with portable assembly, touching anything else than memory in |
+ // an empty assembly statement is meaningless. |
+ bool touchesMemory = Constraints.find("~{memory}") != std::string::npos; |
+ |
+ if (getTarget().getTriple().getArch() == llvm::Triple::le32 && |
+ ResultType->isVoidTy() && HasSideEffect && isEmptyAsm && touchesMemory) { |
+ Builder.CreateFence(llvm::SequentiallyConsistent); |
+ Builder.CreateCall( |
+ llvm::InlineAsm::get(FTy, AsmString, Constraints, HasSideEffect))-> |
+ addAttribute(llvm::AttributeSet::FunctionIndex, |
+ llvm::Attribute::NoUnwind); |
+ } |
+ // @LOCALMOD-END |
+ |
// Slap the source location of the inline asm into a !srcloc metadata on the |
// call. FIXME: Handle metadata for MS-style inline asms. |
if (const GCCAsmStmt *gccAsmStmt = dyn_cast<GCCAsmStmt>(&S)) |